您的位置:首页 > 移动开发

Win 10 apps - Data Binding

2015-08-27 22:37 609 查看
原文地址:https://msdn.microsoft.com/en-us/library/windows/apps/xaml/mt269383.aspx
本文使用VS 2015,创建基于MVVM模式的Universal Windows Platform(UWP) app,实现了几种Data Binding:UI (control) <-->single item, UI(control)<-->a collection of items, 控制Items的呈现, 实现显示选择项详情,以及数据的格式转换。更多详情见Data
binding in depth.

前提

在VS2015中创建UWP app。命名为:Demo_UWP_DataBinding

实例创建

所有的绑定都包括Binding target和Binding resource,通常的:

Binding target:control中的一个属性或者一个UI element.

Binding resource:class 实例的(model或viewmodel)一个属性。

下面例子包括绑定一个简单的item,绑定多个item(ObservableCollection),控制items呈现,显示选择项详情和数据格式转换。

1. 首先添加Model(Recording.cs)和一个ModelView(RecordingViewModel.cs)

public class Recording
{
public string ArtistName { get; set; }
public string CompositionName { get; set; }
public DateTime ReleaseDateTime { get; set; }

public Recording()
{
this.ArtistName = "Demi Dai";
this.CompositionName = "Super Demi Dai";
this.ReleaseDateTime = new DateTime(2016, 1, 1);
}

public string OneLineSummary
{
get
{
return $"{this.CompositionName} by {this.ArtistName}, released: "
+ this.ReleaseDateTime.ToString("d");
}
}
}

public class RecordingViewModel
{
// Binding one single item Start
private Recording defaultRecording = new Recording();
public Recording DefaultRecording { get { return this.defaultRecording; } }
// Binding one single item End

//Binding a collection of items Start
private ObservableCollection<Recording> recordings = new ObservableCollection<Recording>();// implements the INotifyPropertyChanged and INotifyCollectionChanged interfaces. Interface provided change notification to bindings when items are added|removed|the list itself changes
public ObservableCollection<Recording> Recordings { get { return this.recordings; } }
public RecordingViewModel()
{
this.recordings.Add(new Recording()
{
ArtistName = "Johann Sebastian Bach",
CompositionName = "Mass in B minor",
ReleaseDateTime = new DateTime(2015, 7, 8)
});
this.recordings.Add(new Recording()
{
ArtistName = "Ludwig van Beethoven",
CompositionName = "Third Symphony",
ReleaseDateTime = new DateTime(2015, 2, 11)
});
this.recordings.Add(new Recording()
{
ArtistName = "George Frideric Handel",
CompositionName = "Serse",
ReleaseDateTime = new DateTime(1737, 12, 3)
});
}
//Binding a collection of items End
}


值得注意的是:在Binding to a collection of items的时候,我们使用了 ObservableCollection<T>来进行集合绑定,这个一个非常好的方法,因为这个类实现了INotifyPropertyChanged
和INotityCollectionChanged接口,这两个接口当集合中的对象的增加,删除,或者list本身更新的时候,为binding提供了改变提醒作用。也可以实现这个接口绑定control与items同步更新。更多 Data
binding in depth.

2. 暴露Binding source.

在MainPage中添加RecordingsViewModel 属性public sealed partial class BindingPage : Page //Partial class of MainPage
{
public BindingPage()
{
this.InitializeComponent();
this.ViewModel = new RecordingViewModel(); //Binding Source
}

public RecordingViewModel ViewModel { get; set; }
}

3. 转换item显示格式

添加StringFormatter.cs用来转换日期显示格式。其实还有其他的方法实现:比如在Recording.cs中添加一返回值是this.ReleaseDateTime.ToString("d")string属性,名字为ReleaseDate表示返回的是日期,不是日期和时间,或命名为ReleaseDataAsString表示返回的是一个string类型。当然下面这个方法更加的灵活。

public class StringFormatter : Windows.UI.Xaml.Data.IValueConverter
{
// This converts the value object to the string to display.
// This will work with most simple types.
public object Convert(object value, Type targetType,
object parameter, string language)
{
// Retrieve the format string and use it to format the value.
string formatString = parameter as string;
if (!string.IsNullOrEmpty(formatString))
{
return string.Format(formatString, value);
}

// If the format string is null or empty, simply
// call ToString() on the value.
return value.ToString();
}

// No need to implement converting back on a one-way binding
public object ConvertBack(object value, Type targetType,
object parameter, string language)
{
throw new NotImplementedException();
}
}


4. View中添加Binding Target,与Binding Source绑定

<Page
x:Class="Demo_UWP_DataBinding.BindingPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="using:Demo_UWP_DataBinding.Models"
xmlns:tools ="using:Demo_UWP_DataBinding.Tools"
mc:Ignorable="d">
<Page.Resources>
<CollectionViewSource x:Name="RecordingsCollection" Source="{x:Bind ViewModel.Recordings}"/>
<tools:StringFormatter x:Key="StringFormatterValueConverter"/>
</Page.Resources>
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="129*"/>
<ColumnDefinition Width="127*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="115*"/>
<RowDefinition Height="159*"/>
<RowDefinition Height="139*"/>
<RowDefinition Height="355*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" x:Name="textBlock" HorizontalAlignment="Left"
TextWrapping="Wrap" Text="Binding to a single item: " VerticalAlignment="Top"
Margin="5,25,0,0" Height="20" Width="160" FontWeight="Bold" Foreground="#FF14891E"/>
<!--Binding Target:TextBox; Binding Source: RecordingViewModel.DefaultRecording.OneLineSummary-->
<TextBox  Grid.Row="0" Grid.Column="0" Text="{x:Bind ViewModel.DefaultRecording.OneLineSummary}"
VerticalAlignment="Center" Margin="5,82,5,0.8" Height="32" Background="{x:Null}" BorderBrush="{x:Null}" Grid.ColumnSpan="2"
/>

<TextBlock Grid.Row="1" Grid.Column="0"
x:Name="textBlock2" HorizontalAlignment="Left"
TextWrapping="Wrap" Text="Binding to a collection of items: " Ve
4000
rticalAlignment="Top"
Margin="5,15.2,0,0" Height="20" Width="160" FontWeight="Bold" Foreground="#FF14891E"/>
<!--Binding Target:TextBox; Binding Source: RecordingViewModel.Recordings-->
<ListView  Grid.Row="1" Grid.Column="0"
ItemsSource="{x:Bind ViewModel.Recordings}"
HorizontalAlignment="Center" VerticalAlignment="Center" Height="132" Grid.ColumnSpan="2" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Recording">
<TextBlock Text="{x:Bind OneLineSummary}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

<ListView Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
ItemsSource="{x:Bind ViewModel.Recordings}"
HorizontalAlignment="Center" Height="160" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Recording">
<StackPanel Orientation="Horizontal" Margin="6">
<SymbolIcon Symbol="Audio" Margin="0,0,12,0"/>
<StackPanel>
<TextBlock Text="{x:Bind ArtistName}" FontWeight="Bold"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

<TextBlock Grid.Row="3" Grid.Column="0" x:Name="textBlock3" HorizontalAlignment="Left"
TextWrapping="Wrap" Text="Adding a details view: " VerticalAlignment="Top"
Margin="5,5,0,0" Height="20" Width="160" FontWeight="Bold" Foreground="#FF14891E"/>
<!--Means one: SelectedItem-->
<TextBlock Grid.Row="3" Grid.Column="0" x:Name="textBlock4" HorizontalAlignment="Center"
TextWrapping="Wrap" Text="Means one: SelectedItem" VerticalAlignment="Top"
Margin="0,25,0,0" Height="20" FontWeight="Bold"/>
<StackPanel Grid.Row="3" Grid.Column="0" HorizontalAlignment="Center" Margin="0,40,0,0">
<ListView x:Name="RecordingsListView" ItemsSource="{x:Bind ViewModel.Recordings}" Margin="0,10,0,0">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Recording">
<StackPanel Orientation="Horizontal" Margin="2">
<SymbolIcon Symbol="Audio"></SymbolIcon>
<StackPanel>
<TextBlock Text="{x:Bind ArtistName}"/>
<TextBlock Text="{x:Bind CompositionName}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Margin="8" DataContext="{Binding SelectedItem, ElementName=RecordingsListView}">
<TextBlock Text="{Binding ArtistName}"/>
<TextBlock Text="{Binding CompositionName}"/>
<TextBlock Text="{Binding ReleaseDateTime}"/>
</StackPanel>
</StackPanel>
<!--Means two: CollectionViewSource(Page.Resource)-->
<TextBlock Grid.Row="3" Grid.Column="1" x:Name="textBlock5" HorizontalAlignment="Center"
TextWrapping="Wrap" Text="Means two: CollectionViewSource" VerticalAlignment="Top"
Margin="0,25.2,-89,0" Height="20" FontWeight="Bold"  />
<StackPanel Grid.Row="3" Grid.Column="1" HorizontalAlignment="Center" Margin="0,40,0,0">
<ListView ItemsSource="{Binding Source={StaticResource RecordingsCollection}}" Margin="0,10,0,0">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Recording">
<StackPanel Orientation="Horizontal" Margin="2">
<SymbolIcon Symbol="Audio"></SymbolIcon>
<StackPanel>
<TextBlock Text="{x:Bind ArtistName}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Margin="8" DataContext="{Binding Source={StaticResource RecordingsCollection}}">
<TextBlock Text="{Binding ArtistName}"/>
<TextBlock Text="{Binding CompositionName}"/>
<!--Formatting or converting data values for display(Page.Resource)-->
<TextBlock Text="{Binding ReleaseDateTime,
Converter={StaticResource StringFormatterValueConverter},
ConverterParameter=Released: \{0:d\}}"/>
</StackPanel>
</StackPanel>
</Grid>
</Page>

需要注意是:

Binding a single item - 使用了TextBlock来绑定DefaultRecording.OneLineSummary。

Binding items Collection - 使用LIstView来绑定Recordings 集合,首先要添加CollectionViewSource作为page resource。ListView绑定x:Bind ViewModel.Recordings默认显示的是类型名,所以要么将OneLineSummary作为值返回,要么就使用Data template来显示每个item。指定DateTemplate方法有ContentTemplate(Content
control)和ItemTemplate(item control)两种方法,上面也分别给出了ItemTemplate两种实现代码。

Show selectedItem details - 有两种方法:SelectedItem 和 CollectionViewSource(LIstView<ItemSource>和Details View<DataContext>都是绑定到RecordingsCollection(CollectionViewSource),会处理当前选定项,不需要指定CurrentItem,当然如果有需要你也可以指定,以便有歧义的地方),
详情见上面代码。

{x:Bind} vs {Binding}-  前者Wins 10 新增扩展标记,可替代{Binding},但是性能更好,占用内存更小,并更好的支持debugging。在XAML 加载的过程中,{x:Bind}将转换成你认为的binding object,并且该binding object从data source属性中获取值。两种绑定实现的功能差不多,但是{x:Bind}能执行在编译时间生成的特殊目的的代码,{Binding}是runtime object的通用目的检测。

Format item - 首先也要将StringFormatter作为page resource来进行绑定,使用Converter标记来实现最终的灵活格式化。

更多xaml语法见Quickstart: Creating a user interface with XAML 。更多控件布局见Quickstart:
Defining layouts. 

运行效果






内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: