【翻译】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,一经查实,立即删除!

相关文章

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

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

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开发也好。有一种对所有程序员无一例外的刚需 —— 算法与数据…

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

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

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

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

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

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

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

全世界有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;“方法很…

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

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

数学在生活中无处不在,36个生活小故事涵盖小学所有的数学知识!

数学不是脱离生活的&#xff0c;而是源于生活&#xff0c;更要回归于生活。解决生活中遇到的问题&#xff0c;就是最自然的数学应用题。生活场景中的学习&#xff0c;是最生动的体验式学习机会。用学到的数学知识来解决生活中的问题&#xff0c;正是孩子体会数学奥妙的绝佳机会…

面试八股文:你写过自定义任务调度器吗?

最近入职了新公司&#xff0c;尝试阅读祖传代码&#xff0c;记录并更新最近的编程认知。思绪由Q1引发&#xff0c;后续Q2、Q3基于Q1的发散探究Q1. Task.Run、Task.Factory.StartNew 的区别&#xff1f;我们常使用Task.Run和Task.Factory.StartNew创建并启动任务&#xff0c;但是…

快速掌握MATLAB应用,从这一步开始

有人说&#xff0c;“MATLAB除了不会生孩子&#xff0c;什么都会。”矩阵运算、数据可视化、GUI&#xff08;用户界面&#xff09;设计、甚至是连接其他编程语言&#xff0c;MATLAB都能轻松实现&#xff01;那么&#xff0c;MATLAB到底有多厉害&#xff1f;MATLAB拥有丰富的算法…

mobile.php discuz,电脑访问discuz手机版【触屏版跳转标准版的修改方法】

推荐方法&#xff1a;以前我们介绍过如何通过修改Chrome浏览器运行参数的方法来模拟手机访问网站&#xff0c;但是在Chrome 32和33版本以后增加了更加便捷的方法&#xff0c;在开发者工具中只需要设置一下就能方便的模拟各种手机型号的访问效果了。方法如下&#xff1a;1、打开…

深入探究ASP.NET Core读取Request.Body的正确方式

前言相信大家在使用ASP.NET Core进行开发的时候&#xff0c;肯定会涉及到读取Request.Body的场景&#xff0c;毕竟我们大部分的POST请求都是将数据存放到Http的Body当中。因为笔者日常开发所使用的主要也是ASP.NET Core所以笔者也遇到这这种场景&#xff0c;关于本篇文章所套路…

追MM的各种算法

全世界有3.14 % 的人已经关注了数据与算法之美动态规划基本上就是说&#xff1a;你追一个MM的时候&#xff0c;需要对该MM身边的各闺中密友都好&#xff0c;这样你追MM这个问题就分解为对其MM朋友的问题&#xff0c;只有把这些问题都解决了&#xff0c;最终你才能追到MM。因此&…

ML.NET 示例:对象检测

ML.NET 版本API 类型状态应用程序类型数据类型场景机器学习任务算法v1.4动态API最新控制台应用程序图像文件对象检测深度学习Tiny Yolo2 ONNX 模型有关如何构建此应用程序的详细说明&#xff0c;请参阅Microsoft Docs网站上附带的教程。问题对象检测是计算机视觉中的一个经典问…

双十一来了,揭秘菜鸟物流背后的那些算法黑科技

又是一年双十一&#xff0c;又一个巨大的挑战摆在了包括菜鸟网络在内的物流面前&#xff0c;但随着人工智能、大数据的应用越来越广泛&#xff0c;无人化仓储、无人化配送越来越多&#xff0c;供应链越来越扁平化&#xff0c;各种算法应用到物流领域的每一个细节。那么&#xf…