【WPF.NET开发】数据绑定应用场景

目录

1、实现属性更改通知

示例

2、双向绑定​​​更新源

示例

3、对分层数据使用主-从模式

示例

4、对分层 XML 数据使用主-从模式

示例

5、绑定两个控件的属性

示例

6、创建和绑定到 ObservableCollection

示例

7、使用 XMLDataProvider 和 XPath 查询绑定到 XML 数据

示例


1、实现属性更改通知

若要支持 OneWay 或 TwoWay 绑定,从而使绑定目标属性能够自动反映绑定源的动态更改。

示例

若要实现 INotifyPropertyChanged,需要声明 PropertyChanged 事件并创建 OnPropertyChanged 方法。 然后,对于每个需要更改通知的属性,只要进行了更新,就可以调用 OnPropertyChanged

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace SDKSample
{
  // This class implements INotifyPropertyChanged
  // to support one-way and two-way bindings
  // (such that the UI element updates when the source
  // has been changed dynamically)
  public class Person : INotifyPropertyChanged
  {
      private string name;
      // Declare the event
      public event PropertyChangedEventHandler PropertyChanged;

      public Person()
      {
      }

      public Person(string value)
      {
          this.name = value;
      }

      public string PersonName
      {
          get { return name; }
          set
          {
              name = value;
              // Call OnPropertyChanged whenever the property is updated
              OnPropertyChanged();
          }
      }

      // Create the OnPropertyChanged method to raise the event
      // The calling member's name will be used as the parameter.
      protected void OnPropertyChanged([CallerMemberName] string name = null)
      {
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
      }
  }
}

2、双向绑定​​​更新源

本示例介绍了如何使用 UpdateSourceTrigger 属性控制绑定源更新的执行时间。 本主题使用 TextBox 控件作为示例。

示例

TextBox.Text 属性的 UpdateSourceTrigger 默认值为 LostFocus。 这意味着如果应用程序的 TextBox 包含数据绑定 TextBox.Text 属性,则直到 TextBox 失去焦点(例如,将鼠标移到 TextBox 外单击时),键入到 TextBox 中的文本才会更新源。

如果希望在键入过程中更新源,请将该绑定的 PropertyChanged 设置为 UpdateSourceTrigger。 在下面的示例中,突出显示的代码行显示 TextBox 和 TextBlock 的 Text 属性都绑定到相同的源属性。 TextBox 绑定的 UpdateSourceTrigger 属性设置为 PropertyChanged

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:src="clr-namespace:SDKSample"
  xmlns:system="clr-namespace:System;assembly=mscorlib"
  SizeToContent="WidthAndHeight"
  Title="Simple Data Binding Sample">

  <Window.Resources>
    <ObjectDataProvider x:Key="myDataSource" ObjectType="{x:Type src:Person}">
      <ObjectDataProvider.ConstructorParameters>
        <system:String>Joe</system:String>
      </ObjectDataProvider.ConstructorParameters>
    </ObjectDataProvider>
    <Style TargetType="{x:Type Label}">
      <Setter Property="DockPanel.Dock" Value="Top"/>
      <Setter Property="FontSize" Value="12"/>
    </Style>
    <Style TargetType="{x:Type TextBox}">
      <Setter Property="Width" Value="100"/>
      <Setter Property="Height" Value="25"/>
      <Setter Property="DockPanel.Dock" Value="Top"/>
    </Style>
    <Style TargetType="{x:Type TextBlock}">
      <Setter Property="Width" Value="100"/>
      <Setter Property="Height" Value="25"/>
      <Setter Property="DockPanel.Dock" Value="Top"/>
    </Style>
  </Window.Resources>

  <Border Margin="25" BorderBrush="Aqua" BorderThickness="3" Padding="8">
    <DockPanel Width="200" Height="100">
      <Label>Enter a Name:</Label>
      <TextBox>
        <TextBox.Text>
          <Binding Source="{StaticResource myDataSource}" Path="Name"
                   UpdateSourceTrigger="PropertyChanged"/>
        </TextBox.Text>
      </TextBox>

      <Label>The name you entered:</Label>
      <TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=Name}"/>
    </DockPanel>
  </Border>
</Window>

因此,TextBlock 所显示的文本将与用户输入到 TextBox 中的文本相同(因为源发生更改),如该示例的以下屏幕快照所示:

data-binding-simple-binding-sample.png?view=netframeworkdesktop-4.8

如果拥有一个对话框或用户可编辑的窗体,并且希望将源更新延迟到用户完成字段编辑并单击“确定”之后,可以将绑定的 UpdateSourceTrigger 值设置为 Explicit,如下面的示例所示:

<TextBox Name="itemNameTextBox"
         Text="{Binding Path=ItemName, UpdateSourceTrigger=Explicit}" />

如果将 UpdateSourceTrigger 值设置为 Explicit,则仅当应用程序调用 UpdateSource 方法时,该源值才会发生更改。 下面的示例演示如何为 itemNameTextBox 调用 UpdateSource

// itemNameTextBox is an instance of a TextBox
BindingExpression be = itemNameTextBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();

 备注

此方法也可用于其他控件的属性,但请记住,其他大多数属性的默认 UpdateSourceTrigger 值为 PropertyChanged

 备注

UpdateSourceTrigger 属性用于处理源更新,因此仅适用于 TwoWay 或 OneWayToSource 绑定。 若要使 TwoWay 和 OneWayToSource 绑定生效,源对象需要提供属性更改通知。 

3、对分层数据使用主-从模式

此示例演示了如何实现大纲-详细信息方案。

示例

在此示例中,LeagueList 是 Leagues 的集合。 每个 League 都有一个 Name 和一个 Divisions 集合,每个 Division 都有一个名称和一个 Teams 集合。 每个 Team 都有一个团队名称。

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:src="clr-namespace:SDKSample"
  Width="400" Height="180"
  Title="Master-Detail Binding" 
  Background="Silver">
  <Window.Resources>
    <src:LeagueList x:Key="MyList"/>
  <DockPanel DataContext="{Binding Source={StaticResource MyList}}">
    <StackPanel>
      <Label>My Soccer Leagues</Label>
      <ListBox ItemsSource="{Binding}" DisplayMemberPath="Name"
               IsSynchronizedWithCurrentItem="true"/>
    </StackPanel>

    <StackPanel>
      <Label Content="{Binding Path=Name}"/>
      <ListBox ItemsSource="{Binding Path=Divisions}" DisplayMemberPath="Name"
               IsSynchronizedWithCurrentItem="true"/>
    </StackPanel>

    <StackPanel>
      <Label Content="{Binding Path=Divisions/Name}"/>
      <ListBox DisplayMemberPath="Name" ItemsSource="{Binding Path=Divisions/Teams}"/>
    </StackPanel>
  </DockPanel>
</Window>

下面是该示例的一个屏幕快照。 DivisionsListBox 自动跟踪 LeaguesListBox 中的所选项并显示相应的数据。 TeamsListBox 跟踪其他两个 ListBox 控件中的所选项。

databinding-master-detail-scenario.png?view=netframeworkdesktop-4.8

此示例中有两点需要注意:

  1. 三个 ListBox 控件绑定到同一个源。 设置了绑定的 Path 属性以指定希望 ListBox 显示的数据级别。

  2. 必须在要跟踪其所选项的 ListBox 控件上将 IsSynchronizedWithCurrentItem 属性设置为 true。 设置此属性可确保所选项始终设置为 CurrentItem。 或者,如果 ListBox 从 CollectionViewSource 获取数据,它会自动同步所选项和货币。

4、对分层 XML 数据使用主-从模式

此示例演示了如何使用 XML 数据实现大纲-详细信息方案。

示例

在此示例中,数据来自文件 League.xml。 请注意,第三个 ListBox 控件如何通过绑定到其 SelectedValue 属性跟踪第二个 ListBox 控件中的选择更改。

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Multiple ListBox Binding Sample"
  Width="400" Height="200"
  Background="Cornsilk">
    <Window.Resources>
      <XmlDataProvider x:Key="MyList" Source="Data\Leagues.xml"
                       XPath="Leagues/League"/>
      <DataTemplate x:Key="dataTemplate">
        <TextBlock Text="{Binding XPath=@name}" />
      </DataTemplate>
    </Window.Resources>

    <DockPanel DataContext="{Binding Source={StaticResource MyList}}">
      <StackPanel>
        <Label>My Soccer Leagues</Label>
        <ListBox ItemsSource="{Binding}"
                 ItemTemplate="{StaticResource dataTemplate}"
                 IsSynchronizedWithCurrentItem="true"/>
      </StackPanel>

      <StackPanel>
        <Label Content="{Binding XPath=@name}"/>
        <ListBox Name="divisionsListBox"
                 ItemsSource="{Binding XPath=Division}"
                 ItemTemplate="{StaticResource dataTemplate}"
                 IsSynchronizedWithCurrentItem="true"/>
      </StackPanel>

      <StackPanel>
        <Label Content="{Binding XPath=@name}"/>
        <ListBox DataContext="{Binding ElementName=divisionsListBox,
                                       Path=SelectedItem}"
                 ItemsSource="{Binding XPath=Team}"
                 ItemTemplate="{StaticResource dataTemplate}"/>
      </StackPanel>
    </DockPanel>
</Window>

5、绑定两个控件的属性​​​​​​​

此示例演示如何使用 ElementName 属性将一个已实例化控件的属性绑定到另一个控件的属性。

示例

下面的示例演示如何将 Canvas 的 Background 属性绑定到 ComboBox 的 SelectedItem.Content 属性:

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Width="460" Height="200"
  Title="Binding the Properties of Two Controls">

  <Window.Resources>
    <Style TargetType="TextBlock">
      <Setter Property="FontSize" Value="16"/>
      <Setter Property="FontWeight" Value="Bold"/>
      <Setter Property="DockPanel.Dock" Value="Top"/>
      <Setter Property="HorizontalAlignment" Value="Center"/>
    </Style>
    <Style TargetType="Canvas">
      <Setter Property="Height" Value="50"/>
      <Setter Property="Width" Value="50"/>
      <Setter Property="Margin" Value="8"/>
      <Setter Property="DockPanel.Dock" Value="Top"/>
    </Style>
    <Style TargetType="ComboBox">
      <Setter Property="Width" Value="150"/>
      <Setter Property="Margin" Value="8"/>
      <Setter Property="DockPanel.Dock" Value="Top"/>
    </Style>
  </Window.Resources>

  <Border Margin="10" BorderBrush="Silver" BorderThickness="3" Padding="8">
    <DockPanel>
      <TextBlock>Choose a Color:</TextBlock>
      <ComboBox Name="myComboBox" SelectedIndex="0">
        <ComboBoxItem>Green</ComboBoxItem>
        <ComboBoxItem>Blue</ComboBoxItem>
        <ComboBoxItem>Red</ComboBoxItem>
      </ComboBox>
      <Canvas>
        <Canvas.Background>
          <Binding ElementName="myComboBox" Path="SelectedItem.Content"/>
        </Canvas.Background>
      </Canvas>
    </DockPanel>
  </Border>
</Window>

当此示例呈现时,应如下所示:

data-binding-bind-background-canvas.png?view=netframeworkdesktop-4.8

 备注

绑定目标属性(在本例中为 Background 属性)必须是一个依赖属性。 

6、创建和绑定到 ObservableCollection

本示例演示如何创建和绑定到派生自 ObservableCollection<T> 类的集合,该类是一个在添加或移除项时提供通知的集合类。

示例

下面的示例演示 NameList 集合的实现:

public class NameList : ObservableCollection<PersonName>  
{  
    public NameList() : base()  
    {  
        Add(new PersonName("Willa", "Cather"));  
        Add(new PersonName("Isak", "Dinesen"));  
        Add(new PersonName("Victor", "Hugo"));  
        Add(new PersonName("Jules", "Verne"));  
    }  
  }  
  
  public class PersonName  
  {  
      private string firstName;  
      private string lastName;  
  
      public PersonName(string first, string last)  
      {  
          this.firstName = first;  
          this.lastName = last;  
      }  
  
      public string FirstName  
      {  
          get { return firstName; }  
          set { firstName = value; }  
      }  
  
      public string LastName  
      {  
          get { return lastName; }  
          set { lastName = value; }  
      }  
  }  

可以根据使数据可用于 XAML 中的绑定
中的说明,按照与其他公共语言运行时 (CLR) 对象相同的方式使集合可用于绑定。 例如,可以在 XAML 中实例化该集合,并将该集合指定为一个资源,如下所示:

<Window  
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  xmlns:c="clr-namespace:SDKSample"  
  x:Class="SDKSample.Window1"  
  Width="400"  
  Height="280"  
  Title="MultiBinding Sample">  
  
  <Window.Resources>  
    <c:NameList x:Key="NameListData"/>  
  
...  
  
</Window.Resources>  

然后可以绑定到该集合:

<ListBox Width="200"  
         ItemsSource="{Binding Source={StaticResource NameListData}}"  
         ItemTemplate="{StaticResource NameItemTemplate}"  
         IsSynchronizedWithCurrentItem="True"/>  

此处没有显示 NameItemTemplate 的定义。

 备注

集合中的对象必须满足
绑定源概述中所述的要求。 特别是,如果使用 OneWay 或 TwoWay(例如,希望 UI 在源属性发生显著变化时进行更新),则必须实现一个适当的“属性已更改”通知机制,如 INotifyPropertyChanged 接口。

7、使用 XMLDataProvider 和 XPath 查询绑定到 XML 数据

此示例介绍如何使用 XmlDataProvider 绑定到 XML 数据。

使用 XmlDataProvider,在应用程序中可通过数据绑定访问的基础数据可以是 XML 节点的任意树。 也就是说,XmlDataProvider 提供一种将 XML 节点的任意树用作绑定源的简便方式。

示例

在以下示例中,数据作为 XML 数据岛直接嵌入 Resources 部分。 XML 数据岛必须包装在 <x:XData> 标记中,并始终具有一个单一根节点,在本示例中根节点为 Inventory。

 备注

XML 数据的根节点具有一个将 XML 命名空间设置为空字符串的 xmlns 属性。 将 XPath 查询应用到 XAML 页中内联的数据岛时,需要此属性。 在此内联情况下,XAML 以及数据岛会继承 System.Windows 命名空间。 因此,需要将命名空间设置为空白,以防止 XPath 查询被 System.Windows 命名空间限定而误导查询。

<StackPanel
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Background="Cornsilk">

  <StackPanel.Resources>
    <XmlDataProvider x:Key="InventoryData" XPath="Inventory/Books">
      <x:XData>
        <Inventory xmlns="">
          <Books>
            <Book ISBN="0-7356-0562-9" Stock="in" Number="9">
              <Title>XML in Action</Title>
              <Summary>XML Web Technology</Summary>
            </Book>
            <Book ISBN="0-7356-1370-2" Stock="in" Number="8">
              <Title>Programming Microsoft Windows With C#</Title>
              <Summary>C# Programming using the .NET Framework</Summary>
            </Book>
            <Book ISBN="0-7356-1288-9" Stock="out" Number="7">
              <Title>Inside C#</Title>
              <Summary>C# Language Programming</Summary>
            </Book>
            <Book ISBN="0-7356-1377-X" Stock="in" Number="5">
              <Title>Introducing Microsoft .NET</Title>
              <Summary>Overview of .NET Technology</Summary>
            </Book>
            <Book ISBN="0-7356-1448-2" Stock="out" Number="4">
              <Title>Microsoft C# Language Specifications</Title>
              <Summary>The C# language definition</Summary>
            </Book>
          </Books>
          <CDs>
            <CD Stock="in" Number="3">
              <Title>Classical Collection</Title>
              <Summary>Classical Music</Summary>
            </CD>
            <CD Stock="out" Number="9">
              <Title>Jazz Collection</Title>
              <Summary>Jazz Music</Summary>
            </CD>
          </CDs>
        </Inventory>
      </x:XData>
    </XmlDataProvider>
  </StackPanel.Resources>

  <TextBlock FontSize="18" FontWeight="Bold" Margin="10"
    HorizontalAlignment="Center">XML Data Source Sample</TextBlock>
  <ListBox
    Width="400" Height="300" Background="Honeydew">
    <ListBox.ItemsSource>
      <Binding Source="{StaticResource InventoryData}"
               XPath="*[@Stock='out'] | *[@Number>=8 or @Number=3]"/>
    </ListBox.ItemsSource>

    <!--Alternatively, you can do the following. -->
    <!--<ListBox Width="400" Height="300" Background="Honeydew"
      ItemsSource="{Binding Source={StaticResource InventoryData},
      XPath=*[@Stock\=\'out\'] | *[@Number>\=8 or @Number\=3]}">-->

    <ListBox.ItemTemplate>
      <DataTemplate>
        <TextBlock FontSize="12" Foreground="Red">
          <TextBlock.Text>
            <Binding XPath="Title"/>
          </TextBlock.Text>
        </TextBlock>
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
</StackPanel>

如此示例中所示,若要使用属性语法创建相同的绑定声明,必须对特殊字符进行正确转义。 

运行此示例时,ListBox 将显示以下项。 这些项为 Books 下所有元素的 Title,其中 Stock 值为“out”,Number 值为 3 或者大于或等于 8。 请注意,没有返回任何 CD 项,因为 XmlDataProvider 上设置的 XPath 值表示只应公开 Books 元素(本质上是设置筛选器)。

xpath-example-listbox-details.png?view=netframeworkdesktop-4.8

此示例显示书名,因为 DataTemplate 中的 TextBlock 绑定的 XPath 设为“Title”。 如果希望显示属性值,如 ISBN,则应将 XPath 值设置为“@ISBN”。

WPF 中的 XPath 属性使用 XmlNode.SelectNodes 方法处理。 可以修改 XPath 查询以获取不同的结果。 以下是上一示例中对绑定 ListBox 执行 XPath 查询的部分示例:

  • XPath="Book[1]" 将返回第一个 Book 元素(“XML in Action”)。 请注意,XPath 索引从 1 而不是从 0 开始。

  • XPath="Book[@*]" 将返回带有任意属性的所有 Book 元素。

  • XPath="Book[last()-1]" 将返回第二个至最后一个 Book 元素(“Introducing Microsoft .NET”)。

  • XPath="*[position()>3]" 将返回除前 3 个元素之外的所有 Book 元素。

当运行 XPath 查询时,它将返回 XmlNode 或 XmlNode 列表。 XmlNode 是公共语言运行时 (CLR) 对象,这意味着可以使用 Path 属性绑定到公共语言运行时 (CLR) 属性。 再以上述示例为例。 如果该示例的其余部分保持不变,将 TextBlock 绑定更改为下面的值,则将在 ListBox 中看到返回的 XmlNode 的名称。 在此情况下,所有返回节点的名称为“Book”。

<TextBlock FontSize="12" Foreground="Red">
  <TextBlock.Text>
    <Binding Path="Name"/>
  </TextBlock.Text>
</TextBlock>

在某些应用程序中,将 XML 作为 XAML 页的源内的数据岛嵌入可能很不方便,因为在编译时必须知道该数据的确切内容。 因此,还支持从外部 XML 文件获取该数据,如下面的示例所示:

<XmlDataProvider x:Key="BookData" Source="data\bookdata.xml" XPath="Books"/>

如果 XML 数据驻留在远程 XML 文件中,可以通过将适当的 URL 分配给 Source 属性来定义对该数据的访问,如下所示:

<XmlDataProvider x:Key="BookData" Source="http://MyUrl" XPath="Books"/>  

相关推荐

  1. 【WinForm.NET开发数据

    2023-12-25 13:24:01       31 阅读
  2. vue数据

    2023-12-25 13:24:01       39 阅读
  3. WPF数据

    2023-12-25 13:24:01       14 阅读
  4. springmvc数据

    2023-12-25 13:24:01       9 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-25 13:24:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-25 13:24:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-25 13:24:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-25 13:24:01       20 阅读

热门阅读

  1. sklearn网格搜索找寻最优参数

    2023-12-25 13:24:01       40 阅读
  2. 常用git指令

    2023-12-25 13:24:01       35 阅读
  3. 2023年底和2024年节假日及补班日期

    2023-12-25 13:24:01       95 阅读
  4. 门面设计模式

    2023-12-25 13:24:01       36 阅读
  5. Linux系统中跟TCP相关的内核参数

    2023-12-25 13:24:01       37 阅读
  6. vscode windows下 tasks.json 和 launch.json

    2023-12-25 13:24:01       37 阅读
  7. SQL分类

    SQL分类

    2023-12-25 13:24:01      31 阅读
  8. mysql全局事务变量GTID

    2023-12-25 13:24:01       25 阅读
  9. leetcode 131. 分割回文串

    2023-12-25 13:24:01       37 阅读