【翻译】WPF中的数据绑定表达式

有很多文章讨论绑定的概念,并讲解如何使用StaticResources和DynamicResources绑定属性。这些概念使用WPF提供的数据绑定表达式。在本文中,让我们研究WPF提供的不同类型的数据绑定表达式。

介绍

数据绑定是一种强大的技术,它允许数据在UI元素和业务模型之间流动。当业务模型中的数据发生变化时,它会自动将更改反映到UI元素上。

ModelsDescription
OneWaySource → Destination
TwoWaySource ←→ Destination
OneWayToSourceSource ← Destination
OneTimeSource → Destination (only once)

这可以通过WPF提供的不同类型的数据绑定表达式来实现。

数据绑定表达式的类型如下所示。

  • DataContext绑定

  • RelativeSource绑定

  • 集合当前项绑定

1、DataContext绑定

DataContext是一个依赖属性,它是绑定的默认源。Datacontext沿着逻辑树继承。因此,如果您设置一个DataContext来控制逻辑树中的所有子元素,它也将引用同一个DataContext,除非并且直到显式指定了另一个源。

让我们举个例子来更详细地理解它。

1.1 创建一个类Book,如下所示。

public class Book 
{  public string Name {  get;  set;  }  public string Author {  get;  set;  }  
}  

1.2 添加一个XAML文件DataContextBinding.XAML并放置四个TextBlock,如下所示。

<Grid VerticalAlignment="Center">  <Grid.RowDefinitions>  <RowDefinition Height="40" />  <RowDefinition Height="40" />  </Grid.RowDefinitions>  <Grid.ColumnDefinitions>  <ColumnDefinition Width="Auto" />  <ColumnDefinition Width="Auto" />  </Grid.ColumnDefinitions>  <TextBlock Text="Book Name:" FontWeight="Bold" />  <TextBlock Grid.Column="1" />  <TextBlock Text="Author:" FontWeight="Bold" Grid.Row="1" />  <TextBlock Grid.Row="1" Grid.Column="1" />  
</Grid>

现在,让我们看看如何使用这个DataContext属性来显示数据。

它有两种用法,如下所示。

  • 1.使用{Binding}表达式

用于直接绑定DataContext。

创建类Book的实例,初始化其属性,并将类的Name属性分配给Window的DataContext属性。

public partial class DataContextBinding: Window 
{  public DataContextBinding() {  InitializeComponent();  //Create the instance  Book book = new Book();  //initialize the properties  book.Name = "Computer Networking";  //Assign the Property as DataContext  this.DataContext = book.Name;  }  
}  

由于DataContext是沿着逻辑树和数据book继承的,因此Name被绑定到Control Window。Window的所有子元素也将引用同一个对象(book.Name)。

要显示数据,请将DataContext与Textblock绑定,如下所示。

<TextBlock Text="Book Name:" FontWeight="Bold"/>  
<TextBlock Text="{Binding}" Grid.Column="1" />

输出

  1. 使用{Binding Property}表达式

绑定Datacontext的属性。

创建类Book的实例,初始化其属性并将类的实例(Book)分配给Window的DataContext属性。

Book book = new Book();  
//initialize the properties  
book.Name = "Computer Networking";  
book.Author = "James F. Kurose";  
//Assign the instance as DataContext  
this.DataContext = book;  

现在,让我们看看输出。

由于绑定表达式{Binding}用于绑定Book类型的DataContext对象,因此调用ToString()方法,并将数据显示为字符串。为了以正确的格式显示数据,我们必须将数据对象的属性与TextBlock绑定,如下所示:

<TextBlock Text="Book Name:" FontWeight="Bold"/>  
<TextBlock Text="{Binding Name}" Grid.Column="1" />  
<TextBlock Text="Author:" FontWeight="Bold" Grid.Row="1" />  
<TextBlock Text="{Binding Author}" Grid.Row="1" Grid.Column="1"/>

绑定表达式{Binding Name}用于绑定DataContext绑定的Name属性。

输出

2、RelativeSource 绑定

RelativeSource是一个属性,它用相对关系设置绑定源以绑定目标。此扩展主要用于必须将元素的一个属性绑定到同一元素的另一个属性时。

RelativeSource有四种类型,如下所示。

  1. Self

  2. FindAncestor

  3. TemplatedParent

  4. PreviousData

让我们一个一个详细地探讨一下。

2.1 Self

Self用于绑定源和绑定目标相同的场景中。对象的一个属性与同一对象的另一个属性绑定。

例如,让我们取一个高度和宽度相同的椭圆。

在XAML文件中添加下面给出的代码。宽度属性与高度属性相对绑定。

<Grid>  <Ellipse Fill="Black" Height="100" Width="{Binding RelativeSource={RelativeSource Self},Path=Height}">  </Ellipse>  
</Grid>

输出

如果改变椭圆的高度,宽度也会相对变化。

2.2 FindAncestor

顾名思义,当绑定源是绑定目标的祖先(父级)之一时使用此选项。使用FindAncestor扩展,可以找到任何级别的祖先。

让我们举个例子来更清楚地理解它。

步骤

创建XAML,它表示下面给出的元素的逻辑树。

<Grid Name="Parent_3">  <StackPanel Name="Parent_2">  <Border Name="Parent_1">  <StackPanel x:Name="Parent_0" Orientation="Vertical">  <Button></Button>  </StackPanel>  </Border>  </StackPanel>  
</Grid>

现在,让我们使用FindAncestor扩展将祖先的Name属性绑定到子元素button的Content属性。

<Grid Name="Parent_3">  <StackPanel Name="Parent_2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="100">  <Border Name="Parent_1">  <StackPanel x:Name="Parent_0" Orientation="Vertical">  <Button Height="50" Content="{Binding RelativeSource={RelativeSource FindAncestor,  
AncestorType={x:Type StackPanel},  
AncestorLevel=2},Path=Name}"></Button>  </StackPanel>  </Border>  </StackPanel>  
</Grid>

输出

AncestorType为“StackPanel”与AcestorLevel为“2”组合,将button的content属性与StackPanel的Name属性(Parent_2)绑定在一起。

2.3 TemplatedParent

TemplatedParent是一个属性,它使您能够创建一个包含少量未知值的控件模板。这些值取决于应用ControlTemplate的控件的属性。

让我们举个例子来更详细地理解它

步骤

  1. 为按钮创建一个ControlTemplate,如下所示。

<Window.Resources>  <ControlTemplate x:Key="template">  <Canvas>  <Ellipse Height="110" Width="155"  Fill="Black"/>  <Ellipse Height="100" Width="150"  Fill="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Background}">  </Ellipse>  <ContentPresenter Margin="35"  Content="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"/>  </Canvas>  </ControlTemplate>  
</Window.Resources>

在上面给出的代码中,椭圆的Fill属性和ContentPresenter的Content属性依赖于将应用此模板的控件的属性值。

  1. 添加一个按钮并对其应用模板。

<Button Margin="50" Background="Beige" Template="{StaticResource template}" Height="0" Content="Click me" FontSize="22">  
</Button>

在应用模板时,按钮的Background(Beige)与椭圆的Fill属性相对绑定,Content(Click me)与ContentPresenter的Content属性相对绑定。依赖值生效并给出以下输出。

输出

2.4 PreviousData

这是相对使用最少的方式。当数据被分析时,这就出现了,我们需要表示值相对于以前数据的变化。

让我们举个例子来更详细地理解它。

步骤

  1. 创建一个类Data并实现INotifyPropertyChanged接口,如下所示

public class Data: INotifyPropertyChanged 
{  public int DataValue {  get;  set;  }  public event PropertyChangedEventHandler PropertyChanged;  protected void OnPropertyChanged(string PropertyName) {  if (null != PropertyChanged) {  PropertyChanged(this,  new PropertyChangedEventArgs(PropertyName));  }  }  
}   
  1. 创建一个Data类型的列表并将其指定为DataContext。

public RelativeSourcePreviousData() 
{  InitializeComponent();  List < Data > data = new List < Data > ();  data.Add(new Data() {  DataValue = 60  });  data.Add(new Data() {  DataValue = 100  });  data.Add(new Data() {  DataValue = 120  });  this.DataContext = data;  
}   
  1. 在XAML文件中添加ItemsControl。

<ItemsControl ItemsSource="{Binding}"></ItemsControl>
  1. 为其创建ItemsPanel模板,如下。

<ItemsControl ItemsSource="{Binding}">  <ItemsControl.ItemsPanel>  <ItemsPanelTemplate>  <StackPanel Orientation="Vertical" />  </ItemsPanelTemplate>  </ItemsControl.ItemsPanel>  
</ItemsControl>
  1. 现在,为了正确地表示数据,创建DataTemplate,如下所示。

<ItemsControl.ItemTemplate>  <DataTemplate>  <StackPanel Orientation="Horizontal">  <Grid Margin="30,20,0,0">  <Rectangle Width="80" Height="{Binding DataValue}" Fill="Blue" />  <TextBlock Foreground="White" Margin="35,0,0,0" Text="{Binding DataValue}"></TextBlock>  </Grid>  <TextBlock Margin="30,20,0,0" Text="Previous Data:"></TextBlock>  <TextBlock VerticalAlignment="Center" Margin="5,20,0,0" Text="{Binding  RelativeSource={RelativeSource PreviousData}, Path=DataValue}" />  </StackPanel>  </DataTemplate>  
</ItemsControl.ItemTemplate>

输出

蓝色框的高度是列表中项目的值,旧数据显示在右侧。该项的第一个值为“60”。因此,第一项没有旧值。

3、集合当前项绑定

在处理集合时使用。使用这个绑定表达式,您可以非常容易地读取SelectedItem的属性。斜杠是一种特殊运算符,用于处理集合中的当前项。

下面给出了三种表达式。

  1. {Binding / }

  2. {Binding Collection / }

  3. {Binding Collection / Property}

3.1 {Binding / }

此表达式用于绑定DataContext中的当前项。

让我们采取一个示例:

在下面给出的示例中,DataContext是字符串类型的国家/地区的集合,并且与Listbox绑定在一起。

步骤

  1. 创建一个Countries类并添加一个GetCountriesName()方法,该方法返回string数据类型的国家的集合,如下所示。

public class Countries 
{  public static List <string> GetCountriesName() {  List <string> countries = new List <string> ();  foreach(CultureInfo culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures)) {  RegionInfo country = new RegionInfo(culture.LCID);  if (!countries.Contains(country.EnglishName))  countries.Add(country.EnglishName);  }  countries.Sort();  return countries;  }  
}  
  1. 添加一个XAMl文件,一个ListBox和TextBlock,如下所示。

<DockPanel Name="Collection">  <ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True">  </ListBox>  <TextBlock DockPanel.Dock="Top" />  
</DockPanel>
  1. 创建类Countries的实例并将Countries集合指定为DataContext。

public CurrentItemCollection() 
{  InitializeComponent();  Countries countries = new Countries();  this.DataContext = countries.GetCountriesName()  
} 
  1. 绑定TextBlock的Text属性以将其绑定到集合的当前选定项,如下所示。

<TextBlock DockPanel.Dock="Top" Text="{Binding /}" />

输出

一旦列表项被选中,它将在右侧显示所选国家/地区。

3.2 {Binding Collection /}

此表达式用于绑定DataContext中集合属性的当前项。

例如,

DataContext是Countries类

Collection属性是CounriesList,它与ListBox绑定。

步骤

  1. 使用上面创建的类似的国家类,只是略有不同。创建返回类型为RegionInfo的方法。

public static List <RegionInfo> GetCountries() 
{  List <RegionInfo> countries = new List <RegionInfo> ();  foreach(CultureInfo culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures)) {  RegionInfo country = new RegionInfo(culture.LCID);  if (countries.Where(p => p.Name == country.Name).Count() == 0)  countries.Add(country);  }  return countries.OrderBy(p => p.EnglishName).ToList();  
}
  1. 添加RegionInfo类型的CountriesList属性。

private List <RegionInfo> countries = null;  
public List <RegionInfo> CountriesList 
{  get {  if (countries == null)  countries = GetCountries();  return countries;  }  
}  

下面是CountriesList集合中的值的截图。

  1. 将类Countries指定为DataContext,并将Listbox与DataContext的CountriesList属性绑定。

<Window.Resources>  <vm:Countries x:Key="Countries"></vm:Countries>  
</Window.Resources>  
<Grid>  <DockPanel Name="Collection" DataContext="{StaticResource Countries}">  <ListBox ItemsSource="{Binding CountriesList}" IsSynchronizedWithCurrentItem="True">  <ListBox.ItemTemplate>  <DataTemplate>  <TextBlock Text="{Binding EnglishName}"></TextBlock>  </DataTemplate>  </ListBox.ItemTemplate>  </ListBox>  </DockPanel>  
</Grid>
  1. 要计算CountriesList属性的当前项,请绑定TextBlock的Text属性,如下所示。

<TextBlock DockPanel.Dock="Top" Text="{Binding CountriesList/}" HorizontalAlignment="Center" FontSize="16" VerticalAlignment="Center" />

输出

右侧显示DataContext(CountriesList)中集合的当前项(CountriesList)。

3.3 {Binding Collection / Property}

此表达式用于绑定DataContext中集合的当前项的属性。

例如,如果必须计算CountriesList集合的当前项的特定属性。

在这个例子中,我想显示属性“EnglishName”的值。

为此,绑定TextBlock的Text属性,如下所示。

<TextBlock DockPanel.Dock="Top" Text="{Binding CountriesList/EnglishName}" />

输出

现在,当列表中的项被选中时,它显示属性“EnglishName”的值。

结论

我已经详细介绍了所有的数据绑定表达式。我希望这有助于您理解绑定的概念和WPF提供的表达式。


时间如流水,只能流去不流回。

  • 作者:Swati Gupta

  • 原文标题:DataBinding Expressions In WPF

  • 原文链接:https://www.c-sharpcorner.com/article/data-binding-expression-in-wpf/

  • 编辑:沙漠尽头的狼

  • 日期:2021-05-04

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/302693.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java网络编程 个人心得

TCP协议是一个有连接可靠地协议。TCP编程的核心思路 开发服务器端ServerSocket ssnew ServerSocket(9000)ss.accept(); publicclassTcpServer {publicstaticvoidmain(String[] args) {try{ServerSocket ssnewServerSocket (9000);//创建SocketServer对象,并绑定端口Socket sss…

php对表格的处理,JavaScript_js处理表格对table进行修饰,js处理表格 1、行颜色间隔显示 - phpStudy...

js处理表格对table进行修饰js处理表格1、行颜色间隔显示css样式&#xff1a;两个选择器.one{background-color:#33ffcc;}.two{backgound-color:#ffff66;}function trcolor()//控制间隔行颜色显示不同{var tabNode document.getElementsByTagName("table")[0];//获取…

12个关键词,告诉你到底什么是机器学习

全世界只有3.14 % 的人关注了数据与算法之美编者按&#xff1a;随着人工智能(AI)技术对各行各业有越来越深入的影响&#xff0c;我们也更多地在新闻或报告中听到“机器学习”、“深度学习”、“增强学习”、“神经网络”等词汇&#xff0c;对于非专业人士来说略为玄幻。这篇文章…

WPF实现实现圆形菜单

WPF开发者QQ群&#xff1a; 340500857 有小伙伴需要实现圆形菜单。效果如下&#xff1a;一、Xaml代码如下<Window x:Class"WpfRoundMenu.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.mic…

MFC多语言实现方法

2019独角兽企业重金招聘Python工程师标准>>> 一、字符放在DLL资源文件中&#xff0c;切换资源模块(程序默认使用exe模块资源)。 实现要点&#xff1a; 新建一个只包含资源的DLL。通过函数AfxSetResourceHandle设置资源模块。 示意代码为&#xff1a; AfxSetResource…

oracle dbfile数,通过案例学调优之--Oracle参数(db_file_multiblock_read_count)

通过案例学调优之--Oracle参数(db_file_multiblock_read_count)应用环境&#xff1a;操作系统&#xff1a; RedHat EL55Oracle&#xff1a; Oracle 10gR2Oracle DB_FILE_MULTIBLOCK_READ_COUNT是Oracle比较重要的一个全局性参数&#xff0c;可以影响系统级别及sessioin级别。…

转行程序员后,我开始后悔没做这件事

全世界有3.14 % 的人已经关注了数据与算法之美程序 数据结构 算法 ——图灵奖得主&#xff0c;计算机科学家N.Wirth(沃斯)作为程序员&#xff0c;我们做机器学习也好&#xff0c;做python开发也好&#xff0c;java开发也好。有一种对所有程序员无一例外的刚需 —— 算法与数据…

Oracle应用集群详解

了解兼容性Oracle真正应用集群环境要运行与在同一群集数据库的不同版本的Oracle RAC的配置&#xff0c;还必须安装集群。例如&#xff0c;要运行在同一个集群Oracle9i和Oracle 10g&#xff1a;对于Oracle RAC节点上运行的Oracle9i数据库&#xff0c;您必须安装Oracle9i集群&…

工业互联网的两种极端想法和两点反思

目 录1. 概述2. 两种极端想法3. 两点反思1. 概述最近走访了很多企业&#xff0c;涉及到的行业包括&#xff1a;军工、特钢、有色、加工制造&#xff08;海洋钻井平台&#xff09;、建材、纺织等&#xff0c;在与不同的行业交流的过程中&#xff0c;我发现…

oracle重新编译package,如何有效的编译数据库中的失效对象(Package,trigger等)

在utlrp.sql脚本中&#xff0c;Oracle注释到&#xff1a;Rem utlrp.sql - UTiLity script Recompile invalid Pl/sql modulesRemRem DESCRIPTIONRem This is a fairly general script that can be used at any time toRem recompile all existing invalid PL/SQL modules in a …

兵马未至,数据先行,且看如何进行数据挖掘!

从数据中抽取信息从信息中挖掘知识随着大数据时代的到来&#xff0c;数据挖掘的重要性越发显著。可谓是兵马未至&#xff0c;数据先行。所谓数据挖掘&#xff0c;一般是指从大型数据库中将隐藏的预测信息抽取出来的过程&#xff0c;而更为精确的解释就是“从数据中挖掘知识”。…

微软加入字节码联盟,进一步开发支持Blazor 的WebAssembly技术

字节码联盟 (Bytecode Alliance)宣布已正式成为 501(c)(3) 非营利组织&#xff0c;参与组建的企业/组织包括 Fastly、英特尔、Mozilla 和微软&#xff0c;此外还邀请到了 Arm、DFINITY Foundation、Embark Studios、谷歌、Shopify 和加州大学圣地亚哥分校加入并成为正式会员。B…

印象笔记的试用印象

用过有道笔记&#xff0c;现在正在用麦库。总的来说&#xff0c;越来越依赖&#xff0c;感觉非常好用。现在已经超越我手机里的鲜果联播&#xff0c;成为第一常用的软件了。 不说麦库&#xff0c;最近听说evernote出了国内版&#xff0c;想起原来选择手机笔记软件时也比较过eve…

oracle外网监听端口,oracle 11g 修改默认监听端口1521

OS:Oracle Linux Server release 5.7DB:Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production1、查看监听状态&#xff1a;SQL> !lsnrctl statusLSNRCTL for Linux: Version 11.2.0.3.0 - Production on 12-NOV-2013 01:36:29Copyright (c) 1991,…

传说中的贝叶斯统计到底有什么来头?

全世界有3.14 % 的人已经关注了数据与算法之美贝叶斯统计在机器学习中占有一个什么样的地位&#xff0c;它的原理以及实现过程又是如何的&#xff1f;本文对相关概念以及原理进行了介绍。引言&#xff1a;在很多分析学者看来&#xff0c;贝叶斯统计仍然是难以理解的。受机器学习…

更新两个WPF开源项目

前言好久没更新博客了&#xff0c;最近准备重拾博客&#xff0c;将更新恢复起来。开源项目这些年零零散散做了很多项目&#xff0c;准备整理一下&#xff0c;将其开源&#xff0c;现整理了两个项目&#xff1a;绑定引擎&#xff08;BindingEngine&#xff09;&#xff0c;插件式…

OpenGL ES 3D 粒子系统小结

2019独角兽企业重金招聘Python工程师标准>>> 所谓粒子系统可以想象为一堆粒子由一个点或一个面按照一定的规律进行喷射。 粒子系统大致分为2类&#xff1a;一类为“点喷式”&#xff0c;一类为“面喷式”。可以想象前者由一个点进行喷射&#xff0c;类似于焰火&…

理科生用创意毁灭世界,爆笑!

全世界有3.14 % 的人已经关注了数据与算法之美1、青年问禅师&#xff1a;“大师&#xff0c;我很爱我的女朋友&#xff0c;她也有很多优点&#xff0c;但是总有几个缺点让我非常讨厌&#xff0c;有什么方法能让她改变&#xff1f;”禅师浅笑&#xff0c;答&#xff1a;“方法很…

php 派生类 构造,C++派生类的构造函数和析构函数

派生类对象中包含基类对象&#xff0c;因此派生类对象在创建时&#xff0c;除了要调用自身的构造函数进行初始化外&#xff0c;还要调用基类的构造函数初始化其包含的基类对象。因此&#xff0c;程序中任何能够生成派生类对象的语句&#xff0c;都要说明其包含的基类对象是如何…

我的C#/.NET学习诀窍——LINQPad

在我以往的文章中&#xff0c;尤其涉及代码演示的&#xff0c;都使用了同一个工具——LINQPad。但许多客户面对我分享的.linq源文件都迷茫不知所措&#xff0c;因此有必要来聊聊一下这个强大的工具。本文首先将对该工具做个简单的介绍&#xff0c;并且分享一些LINQPad的优点&am…