【翻译】WPF中的数据绑定表达式
有很多文章讨论绑定的概念,并讲解如何使用StaticResources和DynamicResources绑定属性。这些概念使用WPF提供的数据绑定表达式。在本文中,让我们研究WPF提供的不同类型的数据绑定表达式。
介绍
数据绑定是一种强大的技术,它允许数据在UI元素和业务模型之间流动。当业务模型中的数据发生变化时,它会自动将更改反映到UI元素上。
Models | Description |
---|---|
OneWay | Source → Destination |
TwoWay | Source ←→ Destination |
OneWayToSource | Source ← Destination |
OneTime | Source → Destination (only once) |
这可以通过WPF提供的不同类型的数据绑定表达式来实现。
数据绑定表达式的类型如下所示。
- DataContext绑定
- RelativeSource绑定
- ItemSource绑定
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" />
输出
- 使用{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有四种类型,如下所示。
- Self
- FindAncestor
- TemplatedParent
- 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的控件的属性。
让我们举个例子来更详细地理解它
步骤
- 为按钮创建一个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属性依赖于将应用此模板的控件的属性值。
- 添加一个按钮并对其应用模板。
<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
这是相对使用最少的方式。当数据被分析时,这就出现了,我们需要表示值相对于以前数据的变化。
让我们举个例子来更详细地理解它。
步骤
- 创建一个类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));
}
}
}
- 创建一个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;
}
- 在XAML文件中添加ItemsControl。
<ItemsControl ItemsSource="{Binding}"></ItemsControl>
- 为其创建ItemsPanel模板,如下。
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
- 现在,为了正确地表示数据,创建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、ItemSource绑定
在处理集合时使用。使用这个绑定表达式,您可以非常容易地读取SelectedItem的属性。斜杠是一种特殊运算符,用于处理集合中的当前项。
下面给出了三种表达式。
- {Binding / }
- {Binding Collection / }
- {Binding Collection / Property}
3.1 {Binding / }
此表达式用于绑定DataContext中的当前项。
让我们采取一个示例:
在下面给出的示例中,DataContext是字符串类型的国家/地区的集合,并且与Listbox绑定在一起。
步骤
- 创建一个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;
}
}
- 添加一个XAMl文件,一个ListBox和TextBlock,如下所示。
<DockPanel Name="Collection">
<ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True">
</ListBox>
<TextBlock DockPanel.Dock="Top" />
</DockPanel>
- 创建类Countries的实例并将Countries集合指定为DataContext。
public CurrentItemCollection()
{
InitializeComponent();
Countries countries = new Countries();
this.DataContext = countries.GetCountriesName()
}
- 绑定TextBlock的Text属性以将其绑定到集合的当前选定项,如下所示。
<TextBlock DockPanel.Dock="Top" Text="{Binding /}" />
输出
一旦列表项被选中,它将在右侧显示所选国家/地区。
3.2 {Binding Collection /}
此表达式用于绑定DataContext中集合属性的当前项。
例如,
DataContext是Countries类
Collection属性是CounriesList,它与ListBox绑定。
步骤
- 使用上面创建的类似的国家类,只是略有不同。创建返回类型为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();
}
- 添加RegionInfo类型的CountriesList属性。
private List <RegionInfo> countries = null;
public List <RegionInfo> CountriesList
{
get
{
if (countries == null)
countries = GetCountries();
return countries;
}
}
下面是CountriesList集合中的值的截图。
- 将类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>
- 要计算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/
- 翻译、编辑:沙漠之尽头的狼
- 公众号:Dotnet9
- 日期:2021-05-04
【翻译】WPF中的数据绑定表达式的更多相关文章
- WPF中的数据绑定(初级)
关于WPF中的数据绑定,初步探讨 数据绑定属于WPF中比较核心的范畴,以下是对WPF中数据绑定的一个初步探讨.个人感觉还是带有问题性质的叙述比较高效,也比较容易懂 第一,什么是数据绑定? 假定有这么一 ...
- WPF入门教程系列十五——WPF中的数据绑定(一)
使用Windows Presentation Foundation (WPF) 可以很方便的设计出强大的用户界面,同时 WPF提供了数据绑定功能.WPF的数据绑定跟Winform与ASP.NET中的数 ...
- WPF中的数据绑定!!!
引用自:https://msdn.microsoft.com/zh-cn/magazine/cc163299.aspx 数据点: WPF 中的数据绑定 数据点 WPF 中的数据绑定 John Pap ...
- WPF中的数据绑定
WPF中的数据绑定 基础概念 System.Windows.Data.Binding,他会把两个对象(UI对象与UI对象之间,UI对象与.NET数据对象之间)按照指定的方式粘合在一起,并在他们之间建立 ...
- Windows Presentation Foundation(WPF)中的数据绑定(使用XmlDataProvider作控件绑定)
原文:Windows Presentation Foundation(WPF)中的数据绑定(使用XmlDataProvider作控件绑定) ------------------------------ ...
- 【值转换器】 WPF中Image数据绑定Icon对象
原文:[值转换器] WPF中Image数据绑定Icon对象 这是原来的代码: <Image Source="{Binding MenuIcon}" ...
- WPF入门教程系列十八——WPF中的数据绑定(四)
六.排序 如果想以特定的方式对数据进行排序,可以绑定到 CollectionViewSource,而不是直接绑定到 ObjectDataProvider.CollectionViewSource 则会 ...
- WPF入门教程系列十六——WPF中的数据绑定(二)
三.绑定模式 通过上一文章中的示例,学习了简单的绑定方式.在这里的示例,要学习一下绑定的模式,和模式的使用效果. 首先,我们来做一个简单示例,这个示例是根据ListBox中的选中项,去改变TextBl ...
- WPF入门教程系列十七——WPF中的数据绑定(三)
四. XML数据绑定 这次我们来学习新的绑定知识,XML数据绑定.XmlDataProvider 用来绑定 XML 数据,该XML数据可以是嵌入.Xmal文件的 XmlDataProvider 标记中 ...
随机推荐
- 英语单词小程序插件 - EdictPlugin-LTS
1.插件引入 全局app.json配置 "plugins": { "edict-plugin": { "version": "1. ...
- 利用jmeter对WebRTC应用进行压力测试(java)
利用jmeter对WebRTC应用进行压力测试(java) 说明:WebRTC是一款开源的多人即时视频API,与一般的http请求不同,webrtc应用实际压力主要是码流 最近负责了一个WebRTC的 ...
- 翻译:《实用的Python编程》06_03_Producers_consumers
目录 | 上一节 (6.2 自定义迭代) | 下一节 (6.4 生成器表达式) 6.3 生产者,消费者和管道 生成器在设置各种生产者/消费者问题(producer/consumer problems) ...
- 走进docker-聊聊docker网络
容器网络概念 首先了解下linux的网络构成概念 命名空间: Linux在网络栈中引入网络命名空间,将独立的网络协议栈隔离到不同的命令空间中,彼此间无法通信:Docker利用这一特性,实现不容器间的网 ...
- Manjaro Linux平台用pyinstaller打包python可执行文件
技术背景 当我们创建一个python项目,最终的成果如果希望用户能够不依赖于python源代码也能够正常的执行,就会比较的人性化.因为源代码数量众多,很难让每个用户都自行管理所有的源代码,因此我们需要 ...
- 了解 Vue 的 Compsition API
在这篇文章中,我将讲讲 Vue 的 Composition API 为什么比之前的 Options API 要好,以及它是如何工作的. Options API 有什么问题 首先,这里不是要大家放弃 O ...
- 极速精简 Go 版 Logstash
前言 今天来介绍 go-zero 生态的另一个组件 go-stash.这是一个 logstash 的 Go 语言替代版,我们用 go-stash 相比原先的 logstash 节省了2/3的服务器资源 ...
- [递推]B. 【例题2】奇怪汉诺塔
B . [ 例 题 2 ] 奇 怪 汉 诺 塔 B. [例题2]奇怪汉诺塔 B.[例题2]奇怪汉诺塔 题目描述 汉诺塔问题,条件如下: 这里有 A A A. B B B. C C C 和 D D D ...
- 快速了解Web MVC设计模式
MVC概述 MVC即 Model-View-Controller 的缩写,是按照职责划分模块一种设计模式,其中Model是核心. Model:模型.负责执行实际的业务,包含数据操作,可以向视图推送数据 ...
- Linux常用命令-基础部分
Linux介绍 Linux是一款开源的操作系统,免费,开源,安全,高效,处理高并发非常强悍,很多企业级开发项目都部署在Linux/UNIX上. 创始人:Linus Torvalds 林纳斯 Linux ...