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

目录

1、实现属性更改通知

示例

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

示例

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

示例

[4、对分层 XML 数据使用主-从模式](#4、对分层 XML 数据使用主-从模式)

示例

5、绑定两个控件的属性

示例

[6、创建和绑定到 ObservableCollection](#6、创建和绑定到 ObservableCollection)

示例

[7、使用 XMLDataProvider 和 XPath 查询绑定到 XML 数据](#7、使用 XMLDataProvider 和 XPath 查询绑定到 XML 数据)

示例


1、实现属性更改通知

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

示例

若要实现 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。 在下面的示例中,突出显示的代码行显示 TextBoxTextBlockText 属性都绑定到相同的源属性。 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 中的文本相同(因为源发生更改),如该示例的以下屏幕快照所示:

如果拥有一个对话框或用户可编辑的窗体,并且希望将源更新延迟到用户完成字段编辑并单击"确定"之后,可以将绑定的 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 属性用于处理源更新,因此仅适用于 TwoWayOneWayToSource 绑定。 若要使 TwoWayOneWayToSource 绑定生效,源对象需要提供属性更改通知。

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

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

示例

在此示例中,LeagueListLeagues 的集合。 每个 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 控件中的所选项。

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

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

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

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 属性将一个已实例化控件的属性绑定到另一个控件的属性。

示例

下面的示例演示如何将 CanvasBackground 属性绑定到 ComboBoxSelectedItem.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>

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

备注

绑定目标属性(在本例中为 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 的定义。

备注

集合中的对象必须满足

绑定源概述中所述的要求。 特别是,如果使用 OneWayTwoWay(例如,希望 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 元素(本质上是设置筛选器)。

此示例显示书名,因为 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"/>  
相关推荐
冷眼Σ(-᷅_-᷄๑)3 小时前
WPF缩放动画和平移动画叠加后会发生什么?
wpf·动画
△曉風殘月〆5 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
逐·風7 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
SoraLuna8 小时前
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
macos·ui·harmonyos
m0_6569747410 小时前
C#中的集合类及其使用
开发语言·c#
九鼎科技-Leo10 小时前
了解 .NET 运行时与 .NET 框架:基础概念与相互关系
windows·c#·.net
九鼎科技-Leo12 小时前
什么是 ASP.NET Core?与 ASP.NET MVC 有什么区别?
windows·后端·c#·asp.net·mvc·.net
.net开发12 小时前
WPF怎么通过RestSharp向后端发请求
前端·c#·.net·wpf
九鼎科技-Leo12 小时前
WPF 中 NavigationWindow 与 Page 的继承关系解析
wpf
小乖兽技术12 小时前
C#与C++交互开发系列(二十):跨进程通信之共享内存(Shared Memory)
c++·c#·交互·ipc