WP8.1学习系列(第二十三章)——到控件的数据绑定

Applies to Windows and Windows Phone

本主题介绍了如何在使用 C++、C# 或 Visual Basic 的 Windows 应用商店应用中将控件绑定到单个项或将列表控件绑定到项目集合。此外,本主题向你介绍了如何自定义控件项目的显示、如何基于所选内容实现详细信息视图,以及如何转换数据以进行显示。有关更多详细信息,请参阅使用 XAML 进行数据绑定

路线图: 本主题与其他主题有何关联?请参阅:

先决条件

本主题假定你可以使用 Microsoft Visual Basic、Microsoft Visual C# 或 Microsoft Visual C++ 创建基本 Windows 运行时应用。有关创建你的第一个 Windows 运行时应用的说明,请参阅使用 C# 或 Visual Basic 创建你的第一个 Windows 应用商店应用

将控件绑定到单个项目

数据绑定包括一个目标和一个源。目标通常是控件的属性,源通常是数据对象的属性。有关目标和源要求的信息,请参阅使用 XAML 进行数据绑定

下面是将控件绑定到单个项目的一个示例。目标是文本框控件的 Text 属性。源是一个简单的音乐 Recording类。

 
<Grid x:Name="LayoutRoot" Background="#FF0C0C0C">
  <TextBox x:Name="textBox1" Text="{Binding}" FontSize="30"
    Height="120" Width="440" IsReadOnly="True"
    TextWrapping="Wrap" AcceptsReturn="True" />
</Grid>


 
// Constructor
public MainPage()
{
    InitializeComponent();
    
    // Set the data context to a new Recording.
    textBox1.DataContext = new Recording("Chris Sells", "Chris Sells Live",
        new DateTime(2008, 2, 5));
}

// A simple business object
public class Recording
{
    public Recording() { }

    public Recording(string artistName, string cdName, DateTime release)
    {
        Artist = artistName;
        Name = cdName;
        ReleaseDate = release;
    }

    public string Artist { get; set; }
    public string Name { get; set; }
    public DateTime ReleaseDate { get; set; }

    // Override the ToString method.
    public override string ToString()
    {
        return Name + " by " + Artist + ", Released: " + ReleaseDate.ToString("d");
    }
}

上述代码会产生类似下图的输出。

绑定文本框

若要在文本框中显示音乐录音,请通过使用标记扩展将控件的 Text 属性设置为 Binding。在此示例中,默认情况下 Mode 是 OneWay,这意味着数据是从源检索的,但不会将更改传播回到源。

Recording 类有三个公共属性和一个 ToString 方法重写。这三个属性是 ArtistName 和ReleaseDateToString 方法很重要,因为如果未指定任何格式,会出于显示目的在绑定对象上调用 ToString方法。该绑定的 Binding.Source 属性不是直接设置的,而是将 TextBox 控件的 DataContext 属性设置为一个新的 Recording 对象。

将控件绑定到对象的集合

上一个示例展示了用于将数据绑定到控件的语法,但这不是很实际。一个更常见的情形是绑定到业务对象的集合。在 C# 和 Visual Basic 中,通用 ObservableCollection<T> 类是数据绑定的一个很好的集合选择,因为它实现INotifyPropertyChanged 和 INotifyCollectionChanged 接口。当列表中的项目改变时,或列表本身的属性改变时,这些接口向绑定控件提供更改通知。如果你希望你的绑定控件使用集合中的对象属性更改进行更新,则业务对象也应该实现 INotifyPropertyChanged。 有关在 C++ 中进行绑定的信息,请参阅使用 XAML 进行数据绑定

以下示例将音乐 Recording 对象集合绑定到 ComboBox。若要尝试此示例,请单击组合框中的向下箭头,以查看绑定录音列表。

 
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <ComboBox x:Name="ComboBox1" ItemsSource="{Binding}"
        Foreground="Black" FontSize="30" Height="50" Width="780"/>
</Grid>

 
public ObservableCollection<Recording> MyMusic = new ObservableCollection<Recording>();

public Page()
{
    InitializeComponent();

    // Add items to the collection.
    MyMusic.Add(new Recording("Chris Sells", "Chris Sells Live",
        new DateTime(2008, 2, 5)));
    MyMusic.Add(new Recording("Luka Abrus",
        "The Road to Redmond", new DateTime(2007, 4, 3)));
    MyMusic.Add(new Recording("Jim Hance",
        "The Best of Jim Hance", new DateTime(2007, 2, 6)));

    // Set the data context for the combo box.
    ComboBox1.DataContext = MyMusic;
}

上述代码会产生类似下图的输出。

绑定组合框

若要显示 ComboBox 中的音乐录音,则将该控件的 ItemsSource 属性设置为 Binding,并将 ComboBox 控件的 DataContext 属性设置为 Recording 对象的集合,该集合为绑定提供源。针对集合中的每个项都创建了一个 ComboBoxItem。针对每个 Recording 对象将自动调用 ToString,以在组合框项中显示该对象。

通过使用数据模板显示控件中的项目

你可以通过使用项目的 ToString 方法显示列表中的项目。但是,一种更常见的情形是通过使用 DataTemplate来提供数据绑定项目的自定义显示。使用 DataTemplate,可以自定义在控件中显示列表项的方式。通常,通过使用内容控件的 ContentTemplate 属性或项控件的 ItemTemplate 属性来设置数据模板。

以下示例显示了通过使用数据模板绑定到某个组合框的相同录音列表。组合框是 ItemsControl,这意味着通过将每个项目的 ItemTemplate 属性设置为一个数据模板来为每个项目建立数据模板。若要尝试此示例,请单击向下箭头,以查看录音列表。请注意这些录音与上一示例有何不同。在自定义格式中会显示艺术家和 CD 名称。

 
<ComboBox x:Name="ComboBox1" ItemsSource="{Binding}"
  Foreground="Black" FontSize="30" Height="50" Width="450">
  <ComboBox.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal" Margin="2">
        <TextBlock Text="Artist:" Margin="2" />
        <TextBlock Text="{Binding Artist}" Margin="2" />
        <TextBlock Text="CD:" Margin="10,2,0,2" />
        <TextBlock Text="{Binding Name}" Margin="2" />
      </StackPanel>
    </DataTemplate>
  </ComboBox.ItemTemplate>
</ComboBox>

上述代码会产生类似下图的输出。

使用数据模板

在 XAML 中,你可以看到数据模板定义。数据模板包含一个带有四个 TextBlock 控件的 StackPanel。堆叠面板具有一个水平方向,这样四个文本块控件会并排显示。其中两个 TextBlock 控件绑定到 Recording 对象的 Artist 和 Name 属性。另外两个 TextBlock 控件显示静态文本。对于每个绑定项,该绑定提供到 Recording 对象上的属性的路径。如上一示例中所示,该绑定依赖于要设置为录音列表的数据上下文。

此 XAML 使用属性元素语法。有关 XAML 语法的详细信息,请参阅快速入门:使用 XAML 创建用户界面。有关控件布局的详细信息,请参阅快速入门:定义布局

添加详细信息视图

从集合中选择项目时,要显示项目的详细信息,你必须创建相应的 UI 并将该 UI 绑定到你希望其显示的数据。此外,必须将 CollectionViewSource 用作数据上下文以使详细信息视图能够绑定到当前项。

以下示例显示了相同的录音列表,但这次该列表是某个 CollectionViewSource 实例的数据源。会将整个页面或用户控件的数据上下文设置为集合视图源,且组合框和详细信息视图会继承数据上下文。这使得组合框绑定到集合并且能够显示相同的项列表,同时详细信息视图会自动绑定到当前项。详细信息视图不需要明确绑定到当前项,因为集合视图源自动提供数据的相应级别。

若要尝试此示例,请单击向下箭头,并选择不同的录音。请注意,艺术家、CD 名称和发布日期会显示在详细信息视图中的相应组合框下方。

 
<!--The UI for the details view-->
<StackPanel x:Name="RecordingDetails">
  <TextBlock Text="{Binding Artist}" FontWeight="Bold" FontSize="30" />
  <TextBlock Text="{Binding Name}" FontStyle="Italic" FontSize="30" />
  <TextBlock Text="{Binding ReleaseDate}" FontSize="30" />
</StackPanel>

 
// Set the DataContext on the parent object instead of the ComboBox
// so that both the ComboBox and details view can inherit it.  
// ComboBox1.DataContext = MyMusic;
this.DataContext = new CollectionViewSource { Source = MyMusic };

上述代码会产生类似下图的输出。

显示详细信息视图

在此示例中,将向包含现有组合框的用户控件中添加一个 StackPanel。接下来是包含用于显示录音详细信息的三个文本块的一个堆叠面板。每个文本块的 Text 属性将绑定到 Recording 对象上的某个属性。

转换数据以在控件中显示

如果需要在控件中设置某个非字符串类型(如 TextBox)的格式并显示该类型,则可以使用转换器。例如,你可以显示一个标签和一个已设置格式的日期,而不是仅显示该日期。

以下示例将展示在录音列表中发布日期的某个转换器实现。若要尝试此示例,请单击向下箭头,并选择不同的录音。请注意,下拉列表和详细信息视图中的发布日期会以自定义格式显示。

 
<UserControl x:Class="TestDataBindingQS.Page2"
  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:local="using:TestDataBindingQS"
  mc:Ignorable="d"
  d:DesignHeight="768" d:DesignWidth="1366">

  <UserControl.Resources>
    <local:StringFormatter x:Key="StringConverter"/>
  </UserControl.Resources>

  <Grid x:Name="LayoutRoot" Background="#FF0C0C0C">

    <StackPanel Width="750" Height="200"
      VerticalAlignment="Center" HorizontalAlignment="Center">
    
      <ComboBox x:Name="ComboBox1" ItemsSource="{Binding}" 
        Foreground="Black" FontSize="30" Height="50" Width="750">
        <ComboBox.ItemTemplate>
          <DataTemplate>
            <StackPanel Orientation="Horizontal" Margin="2">
              <TextBlock Text="Artist:" Margin="2" />
              <TextBlock Text="{Binding Artist}" Margin="2" />
              <TextBlock Text="CD:" Margin="10,2,0,2" />
              <TextBlock Text="{Binding Name}" Margin="2" />
            </StackPanel>
          </DataTemplate>
        </ComboBox.ItemTemplate>
      </ComboBox>

      <!--The UI for the details view-->
      <StackPanel x:Name="RecordingDetails">
        <TextBlock Text="{Binding Artist}" FontSize="30" FontWeight="Bold" />
        <TextBlock Text="{Binding Name}" FontSize="30" FontStyle="Italic" />
        <TextBlock Text="{Binding ReleaseDate,
          Converter={StaticResource StringConverter},
          ConverterParameter=Released: {0:d}}" FontSize="30"  />
      </StackPanel>

    </StackPanel>
  
  </Grid>

</UserControl>

 
public class StringFormatter : 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, System.Globalization.CultureInfo culture)
    {
        // Retrieve the format string and use it to format the value.
        string formatString = parameter as string;
        if (!string.IsNullOrEmpty(formatString))
        {
            return string.Format(culture, 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, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

上述代码会产生类似下图的输出。

显示具有自定义格式的日期

转换器是从 IValueConverter 接口派生出的一个类。IValueConverter 有两种方法:Convert 和ConvertBack。对于从数据源到绑定目标的单向绑定,仅仅需要实现 Convert 方法。此示例中的转换器是相当通用的。可以将所需的字符串格式作为参数传递,且转换器会使用 String.Format 方法执行转换。如果未传递任何格式字符串,则转换器会返回在对象上调用 ToString 的结果。

在你实现转换器之后,你要立即创建转换器类的一个实例,并通知绑定使用此实例。在此示例中,这是在 XAML 中执行的。转换器的实例是作为静态资源创建的,并会向其分配一个键。在绑定上设置转换器属性时,会使用该键。

有关如何转换数据以便在控件中显示的详细信息,请参阅IValueConverter

原文地址:https://www.cnblogs.com/bvin/p/4285037.html