系列文章目录
1.WPF学习 - .NET相关知识
2.WPF学习 - XAML 之简单介绍
3.WPF学习 - XAML之基本语法
4.WPF学习 -XAML 之 x 名称空间
文章目录
前言
界面应用程序,比较重要的是界面和底层数据的结合。Binding是非常重要的一部分。
参考《WPF深入浅出》,结合VS2022 实际操作,算是对Binding有初步的了解。
还需要再深入学习。
程序的本质是 数据+ 算法
应用程序:三层结构,数据存储层(内存),数据处理层(逻辑代码),数据展示层(UI)
WPF中:
- 数据存储层:数据库和文件系统来构建
- 数据处理:.NET framework中的ADO.NET等基本类处理
- 数据展示:WPF界面应用程序
- 数据处理和数据展示,两层的沟通,通过Data Binding
一、Data Binding是什么?
Binding字面意思:绑定、关联、键联
如果把Binding比作数据的桥梁,一端是数据源(source),另一端是数据目标(Target),通过这个桥梁,数据实现了流通。
如果把这个桥梁升级为高速公路,那么我们可以设置数据流通是单向or双向的,可以设置数据放行时间,甚至可以设置“关卡”,便于数据类型转换或者检验数据的正确性
1.1 Binding特性 - Binding路径
数据源是一个对象,对象可能有很多数据(成员变量),这些数据通过属性(get、set封装之后称之为属性)暴露给外界。
对象的哪一个数据和界面控件进行绑定,或者说界面控件显示哪一个数据–>UI元素和对象的某个具体属性绑定的过程,称之为Binding路径
D
a
t
a
S
o
u
r
c
e
(
a
,
b
,
c
)
=
=
=
=
>
D
a
t
a
B
i
n
g
(
A
)
=
=
=
=
>
D
a
t
a
T
a
r
g
e
t
(
控件)
DataSource (a,b,c)====>DataBing(A)====>DataTarget(控件)
DataSource(a,b,c)====>DataBing(A)====>DataTarget(控件)
1.2 Binding特性 - 自动机制
我们想要当属性值变化时,UI元素能立马Get到这个值发生了变化 - 这个就称为自动机制。
具体怎么做呢?
- 让作为数据源的类实现System.ComponentModel名称空间中的INotifyPropertyChanged接口。
- 在属性的set语句中激发一个PropertyChanged事件。
//1.实现INotifyPropertyChanged接口
public partial class MainWindow : Window, INotifyPropertyChanged
{
//2.声明事件,委托类型为PropertyChangedEventHandler
public event PropertyChangedEventHandler?PropertyChanged;
private string name1;
public string Name1
{
get { return name1; }
set
{
name1 = value;
//3.事件触发
if (this.PropertyChanged != null)
//这个类的属性发生了变化(事件对应的委托处理的PropertyChanged )
{
//
this.PropertyChanged(this, new PropertyChangedEventArgs("Name1"));
}
}
}
-
ui界面添加TextBox,值和Name1属性关联
-
UI界面添加Button,点击时更改Name1的值
<Button x:Name="ChangeText" Content="change" HorizontalAlignment="Left" Margin="97,111,0,0" VerticalAlignment="Top" Width="75" Click="ChangeText_Click"/>
<TextBox x:Name="ShowName" HorizontalAlignment="Left" Margin="14,36,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="164" Height="37"/>
public MainWindow()
{
InitializeComponent();
//4.show binding process
Binding binding = new Binding();
binding.Source = this;
binding.Path = new PropertyPath("Name1");
//5. ui 和data source绑定
BindingOperations.SetBinding(this.ShowName, TextBox.TextProperty, binding);
}
private void ChangeText_Click(object sender, RoutedEventArgs e)
{
Name1 = "wqrrong";
}
流程:
ChangeText按键点击 (修改类中Name1属性的值 )
因为MainWindow 类实现了INotifyPropertyChanged接口,所以当Name1属性的值修改时,会通知到系统
因为TextBox的TextProperty属性和Name1属性进行了绑定,系统告知Name1发生了变化,会同步刷新TextBox的
1.3 ui基类对Binding 的封装
UI元素的基类FrameworkElement对BindingOperations.SetBinding
()进行了封装,封装之后的函数setBinding
public BindingExpression SetBinding(DependencyProperty dp, string path);
public BindingExpressionBase SetBinding(DependencyProperty dp, BindingBase binding);
有了这个封装之后,可以这样简单使用:
方法一 逻辑代码使用SetBinding
//target ,属性名 ,source
this.ShowName.SetBinding(TextBox.TextProperty,new Binding("Name1"){ Source = this });
方法二 UI界面设置binding
<TextBox x:Name="ShowName" HorizontalAlignment="Left" Margin="14,36,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="164" Height="37"/>
<TextBox x:Name="TextBox2" Text="{Binding Text, ElementName=ShowName}" VerticalAlignment="Top" Width="120" HorizontalAlignment="Left" Margin="214,36,0,0" TextWrapping="Wrap" />
让第二个Textbox和第一个Textbox(Target)- 的text属性(Path)进行binding
上面是省略了path,也可以这么写
<TextBox x:Name="TextBox2" Text="{Binding Path=Text, ElementName=ShowName}" VerticalAlignment="Top" Width="120" HorizontalAlignment="Left" Margin="214,36,0,0" TextWrapping="Wrap" />
方法 一和方法二是等价的
binding模型*
binding数据源要求:是一个对象,通过属性(property)公开自己的数据,实现 INotifyPropertyChanged接口
二、 Binding方向控制-BindingMode
单向:如果数据只想给用户看,而不可以修改,可以设置为单向的。
双向:用户可以查看当前数据,也可以修改数据,这个数据被其他地方修改时,用户也能及时查看
控制Binding数据流向属性的类Mode,可选类型:
2.1 BindingMode枚举值
BindingMode是一个枚举类,枚举值有:
- Default:Binding模式根据实际情况确定,如果值时可编辑的-双向(TextBox.Text),只读的-单向(TextBlok.Text)
- OneWay:单向, 仅当源属性发生更改时更新目标属性。
- OneTime 仅当应用程序启动时或 DataContext 进行更改时更新目标属性。
- OneWayToSource :反向Binding,在Target属性更改时更新Source属性。
2.1.1 双向实例
用一个TextBox显示slider的值,修改textBox,slider会滑动,滑动slider,textbox显示值也会同时刷新
<Slider x:Name="Slider1" HorizontalAlignment="Left" Margin="10,90,0,0" VerticalAlignment="Top" Width="314" Maximum="100"/>
<TextBox x:Name="TextBox3" Text="{Binding Value, ElementName=Slider1, Mode=TwoWay, StringFormat=\{0:F4\}, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="10,59,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" />
2.2 UpdateSourceTrigger 枚举 - 触发数据源(source)更新的方式
在设定Binding时,还会设置UpdateSourceTrigger属性
这个枚举选项有:
- Default:默认值,源会根据绑定的属性来更新
- PropertyChanged:Target属性值改变,源会立即更新 – 同步刷新
- LostFocus :Target控件失去焦点时,Source才更新值 – 当鼠标离开Target控件时
- Explicit :不会自动更新,需要手动调用UpdateSource来进行更新
三、 Binding path
Binding类的构造器参数列表,以一个字符串来表示Path,但是Path的实际类型是PropertyPath。根据前面的所有例子,制定Path有以下几种方式。比如用Text的值和slider的value属性进行绑定
- xaml
- C#
- C# – Binding构造器
3.1 多级路径
Binding支持多级路径, 例如A的B成员的C属性 - 一路“.”下去 A.B.C
textbox和另一个textbox内容的长度进行binding
3.2 索引器
集合类型的索引器(indexer) - 带参属性
索引器也能作为Path。比如TextBox显示另一个Text的第四个字符
当使用集合或者Data View作为 binding source时,可以设置Source的默认元素作为Path
3.3.1 集合元素的子集合
source为集合元素的子集合 - 一路“/”下去
3.3.2 没有“path”的Binding
如果Binding source本身就是个数据,则不需要指定path,比如 string、int基本类型
path设置为“.”就可以了
,在xaml可以可以省略不行,但是在C#代码中必须要写
三、 不同Source 的Binding方法
- 普通CLR属性的集合类型指定为source:集合类型有数组,List<T>,ObservableCollection<T>等。一般需要把一个集合作为ItemsControl派生类的的数据源来使用,把控件的ItemsSource属性Binding到一个集合对象上
- 把ADO.NET数据对象指定为source:包括Data Table和DataView 等对象
- XML数据:使用XMlDataProvider 把XML数据指定为source,Target一般是TreeView,Menu等树状结构
- 依赖对象(dependency property):
- 把容器的DataContext作为source:Data binding的默认方式,明确知道从哪个属性获取值,但不知道具体哪个对象 ,可以先设定Path,不设置Source,让它自己去寻找Binding source。Binding会自动把控件的DataContext当做source,沿着控件树,一层一层向外寻找,知道找到带有Path指定的属性位置
- 通过ElementName指定source:C#中,可以将对象作为source 赋值给Binding,但XAML无法访问对象,所以只能用对象的Name属性来找到对象。
3.1 单个CLR类型对象
普通CLR类型的对象作为source,方法有两种,一种是把对象赋值给Binding.Souce
。另一种是source对象的Name赋值给Binding.ElementName
。
- 而这种作为数据源的类中需要实现
INotifyPropertyChange
接口,或者这个CLR属性是UI控件的某个属性(UI控件基类实现了INotifyPropertyChange
接口)
下面是Source对象(类对象)的Name1属性
赋值给名为ShowName控件的TextProperty
属性的两种方法
3.1.1 逻辑代码 - SetBinding
通过SetBinding ,设定了Bindging Target(path){source}
this.ShowName.SetBinding(TextBox.TextProperty
,new Binding("Name1"){ Source = this });
3.1.2 ui - Binding.ElementName
将Source对象的Name赋值给Binding.ElementName
通过"{Binding Value,ElementName=Source对象Name ,UpdateSourceTrigger=}" 方式在xaml中绑定
<Slider x:Name="Slider1" HorizontalAlignment="Left" Margin="10,90,0,0" VerticalAlignment="Top" Width="314" Maximum="100"/>
<TextBox x:Name="TextBox3" Text="{Binding Value, ElementName=Slider1, Mode=TwoWay, StringFormat=\{0:F4\}, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="10,59,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" />
3.2 已知path(属性)求source(类对象)
- 使用
DataContext
作为Binding的Source
在WPF控件基类FrameworkElement
类里定义了DataContext
属性,所有的WPF控件(包括容器控件)都拥有这个属性,WPF UI布局树是树形结构,每个结点都是一个控件 ==>每个结点都有一个DataContext
属性
当一个Binding知道path(某个具体的属性),而不知道具体哪一个对象时,可以自下而上依次寻找每个结点的DataContext
是否具有Path所指定的属性,找到时即封这个对象为Source,如果找不到Source 那也拿不到数据
3.2.1 实操
3.2.1.1 目标实现
- SliderValue作为MainWindow的属性
- 编号1的文本框和Slider控件Binding,双向同步更新(Mode=TwoWay),Slider作为source
- Slider控件作为Target,SliderValue作为Source,通过Mode=OneWayToSource,反向更新SliderValue值
- 编号2文本框作为Target,SliderValue作为Source,通过OneWay进行Binding,这样同步查看SliderValue的值。
3.2.1.2 初步代码以及问题
一开始参考《WPF深入浅出》,代码如下
- 新增SliderValue属性
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler?PropertyChanged;
public int SliderValue{ get; set; }
- 修改Xaml
- 设定上下文
DataContext
- TextBox3和Slider双向绑定
- Slider和SliderValue 反向更新数据Source,binding 方式为 path,指定路径
- TextBox4和SliderValue 也通过path方式绑定
- 这样就实现了
TextBox3 = Slider控件 - >SliderValue ->TextBox4
的数据通路
<Grid>
<Grid.DataContext>this</Grid.DataContext><!--数据上下文指定为当前类-->
<Slider x:Name="Slider1" Value="{Binding Path=SliderValue,Mode=OneWayToSource}" HorizontalAlignment="Left" Margin="10,90,0,0" VerticalAlignment="Top" Width="314" Maximum="100"/>
<TextBox x:Name="TextBox3" HorizontalAlignment="Left" Margin="10,59,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Value, ElementName=Slider1, Mode=TwoWay, StringFormat=\{0:F0\}, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="TextBox4" Text="{Binding Path=SliderValue,Mode=OneWay}" HorizontalAlignment="Left" Margin="10,121,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" />
<Grid>
问题:窗口能正常加载,但是找不到数据源
3.2.1.3 解决办法
尝试在逻辑代码中指定数据上下文,成功!
public MainWindow()
{
this.SliderValue = 50;//initial value
InitializeComponent();
MyGrid.DataContext = this;//method1 set Grid DataContext
//method2:单独指定通过path Binding的控件的数据上下文(DataContext)
/* TextBox4.DataContext = this;
Slider1.DataContext = this;*/
3.2.1.4 如何在xaml中设置Datacontext?–未解决
- xaml中指定DataContext
<Grid.Resources>
<local:MainWindow x:Key="MyMainWindowResource"/>
</Grid.Resources>
<Grid.DataContext>
<Binding Source="MyMainWindowResource" />
</Grid.DataContext>
Grid.Resources应该是指
Grid.Resources采用MainWindow,且 命名为MyMainWindowResource?
<Grid.DataContext> 指和MyMainWindowResource 进行绑定
但是不能成功刷新SliderValue的值,也就说通过path 进行binding失败了
<Window.DataContext>this</Window.DataContext>
<Grid x:Name="MyGrid">
改成这样也不行
whyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy???
疯了
先放弃,后面再来看
也许书中用的是一个固定值,而我像显示的是动态的值?
DataContext是一个依赖属性,会依次往UI元素树向下传递
使用场景
- ui的多个控件都使用binding关注同一个对象
- 作为source的对象不能直接被访问时(比如B窗口使用A窗口的控件,作为自己的Binding源,但A窗口的控件时private,这个时候就可以把控件的值作为窗体A的DataContext(该控件的属性是public)-- 待验证)
外层容器的DataContext相当于制高点,只要把数据放上去,其内层的元素都能看见。DataContext本身是一个依赖属性,可以使用Binding把它关联到一个数据源上。
3.3 集合对象
WPF中列表式控件都派生于ItemsControl类,也都继承了这个类中的ItemsSource属性。
ItemsSource 可接手IEnumerable派生类实例作为自己值
所以可以被迭代遍历的集合都继承了IEnumerable这个接口
也就是说,列表式控件 中ItemsSource 都可以和集合对象进行binding
可迭代遍历的集合类型有:数组,List 等
ItemsControl派生类,都有自己对应的条目容器Item Container,ListBox的条目容器是ListBoxItem。ComboBox的条目容器是ComboBoxItem。
ItemsSource里面存放的是一条一条的数据。条目容器是数据的外衣。
3.3.1 实操
使用listbox控件,绑定stulist,显示他的Name项。
textbox显示当前选中的item -id
步骤:
- 定义一个student类
- 声明List<Student>对象stulist
- stulist 和ListBox绑定
- Textbox和ListBox的Selected.id进行绑定
public MainWindow()
{
InitializeComponent();
List<Student> stulist = new List<Student>()
{
new Student(){Id=0,Name="Q1",Age=10 },
new Student() { Id = 1, Name = "Q2", Age = 11 },
new Student() { Id = 2, Name = "Q3", Age = 12 },
new Student() { Id = 3, Name = "Q4", Age = 13 },
};
ListBoxStudents.ItemsSource=stulist;
ListBoxStudents.DisplayMemberPath = "Name";
}
public class Student
{
public int Id { get; set; }
public int Age { get; set; }
public string? Name { get; set; }
}
<ListBox x:Name="ListBoxStudents" Margin="0,165,502,150"/>
<TextBlock HorizontalAlignment="Left" Margin="4,303,0,0" TextWrapping="Wrap" Text="CurrentItem" VerticalAlignment="Top"/>
<TextBox x:Name="ShowListBoxItem" Text="{Binding ElementName=ListBoxStudents, Path=SelectedItem.Id}" HorizontalAlignment="Left" Margin="122,301,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
3.3.1.1 实操疑问 – 待解决
为什么在xaml界面binding ListBox 会失败
TextBox绑定时为什么不能使用下列格式?–使用Source?
TextBox x:Name="ShowListBoxItem" Text="{Binding Source=ListBoxStudents, Path=SelectedItem.Id}"
3.3.1.2 量身打造ListBox
ItemsControl创建Bindding - DisplayMemberSelector的SelectTemplate方法完成。这个方法返回一个DataTemplate对象。
如果没有显示为ListBox指定DataTemplate,系统默认创建一个DataTemp –数据显示模板? 后续数据变化时,不能刷新界面。如果要实时刷新,需要使用ObservableCollection
- 删除逻辑代码
ListBoxStudents.DisplayMemberPath = "Name";
- 修改xaml
<ListBox x:Name="ListBoxStudents" Margin="0,165,502,150">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Id}" Width="30"/>
<TextBlock Text="{Binding Path=Name}" Width="30"/>
<TextBlock Text="{Binding Path=Age}" Width="30"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
3.4 ADO.NET
ADO.NET
是一个.net framework中的一个类,专门用来处理数据。通过它,可以访问SQL,ODBC,Oracle,OLE,XML,DB,等数据源并在其中检索、更新、操作数据。
DataTable
是一种行列的数据结构,是一个二维的数组,能够转化为试图,转化为表,在和数据库交互时有重要作用;它常常作为DataSet的一个子集
LINQ:Language Integrated Query
语言继承查询,LINQ是一组语言特性和API,可以使用统一的方式编写各种查询。用于保存和检索来自不同数据源的数据,从而消除了编程语音和数据库之间的不匹配,以及为不同类型的数据源提供单个查询接口。
LINQ总是使用对象,因此可以使用相同的查询语法来查询和转换XML、对象集合、SQL数据库、ADO.NET数据库以及任何其他可用的LINQ提供程序格式的数据原文链接
数据库 → DataTable → (通过LINQ转换数据) → UI列表控件
WPF支持在列表控件中与DataTable中建立Binding
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Age");
dt.Rows.Add("QQ1","38");
dt.Rows.Add("QQ2","48");
ListBoxDataTable.DisplayMemberPath = "Name";
ListBoxDataTable.ItemsSource = dt.DefaultView;
通过上面代码设置 可以让listbox显示Name 列
怎么设置多列或者全部显示???
3.5 xml
.NET framework目前提供了两套处理XML数据的类库XmlDocumenth和LINQ
3.5.1 实操
使用ListView显示xml 内容
- 新建xml文件,包含了StudentList
- 创建ListView控件
- 新建button ,点击时加载xml数据
代码如下:
private void LoadXml2ListView_Click(object sender, RoutedEventArgs e)
{
XmlDocument doc=new XmlDocument();
doc.Load(@"D:\test\WPF\Binding\Binding\StudentList.xml");
XmlDataProvider xdp = new XmlDataProvider();
xdp.Document=doc;
//选择暴露的数据 - xml中的student
xdp.XPath = @"/StudentList/Student";
ListViewXml.DataContext = xdp;
ListViewXml.SetBinding(ListView.ItemsSourceProperty, new Binding());
}
<ListView x:Name="ListViewXml" d:ItemsSource="{d:SampleData ItemCount=5}" Margin="276,152,261,239">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" Width="40" DisplayMemberBinding="{Binding XPath=@Id}"/>
<GridViewColumn Header="Name" Width="60" DisplayMemberBinding="{Binding XPath=Name}"/>
</GridView>
</ListView.View>
</ListView>
<Button x:Name="LoadXml2ListView" Content="LoadXml" HorizontalAlignment="Left" Margin="276,289,0,0" VerticalAlignment="Top" Click="LoadXml2ListView_Click"/>
</Grid>
<?xml version="1.0" encoding="utf-8"?>
<StudentList>
<Student Id="1">
<Name>Tim</Name>
</Student>
<Student Id="2">
<Name>Xim</Name>
</Student>
<Student Id="3">
<Name>Yim</Name>
</Student>
<Student Id="4">
<Name>Zim</Name>
</Student>
<Student Id="5">
<Name>Nim</Name>
</Student>
</StudentList>
ListViewXml.SetBinding(ListView.ItemsSourceProperty, new Binding());
这里通过path 进行binding,并设定了DataContext是xdp。
xml需要通过Xpath进行binding
@加字符串 = xml元素的属性。如果不加@则表示这是子级元素
Xpath作为xml语言的功能,有着一整套语法。–在MSDN中可以查到
3.6 LINQ
LINQ 可以避免好几层foreach 嵌套循环。
按照《WPF深入浅出》书上,操作步骤如下:
- 修改xml中内容
- 添加Student类
- student类在这里什么作用?–在找到T开头的元素后,解析这个元素,并用解析的值作为student 实例的属性值。最后将student返回到ItemSource
- 添加button 及其响应事件,在click时,搜索xml文件中Name为T开头的元素
- 修改xaml ,
不再通过Xpath绑定
,- 这里的Binding方式是什么? 通过path?-对
DisplayMemberBinding="{Binding Id}"
DisplayMemberBinding是GridViewColumn的一个属性,此处相当于和ItemSource中的Id数据项绑定
等价于DisplayMemberBinding="{Binding Path=Id}"
- 这里的Binding方式是什么? 通过path?-对
<?xml version="1.0" encoding="utf-8"?>
<StudentList>
<Class>
<Student Id="1" Name="Aim" Age="22"/>
<Student Id="2" Name="Bim" Age="23"/>
<Student Id="3" Name="Cim" Age="24"/>
<Student Id="7" Name="Tony" Age="20"/>
<Student Id="8" Name="Timi" Age="28"/>
</Class>
<Class>
<Student Id="4" Name="Dim" Age="25"/>
<Student Id="5" Name="Eim" Age="26"/>
<Student Id="6" Name="Tim" Age="27"/>
</Class>
</StudentList>
public class Student
{
public int Id { get; set; }
public int Age { get; set; }
public string? Name { get; set; }
}
private void SearchXml_Click(object sender, RoutedEventArgs e)
{
XDocument doc = XDocument.Load(@"D:\test\WPF\Binding\Binding\StudentList.xml");
ListViewXml.ItemsSource =
from element in doc.Descendants("Student")
where element.Attribute("Name").Value.StartsWith("T")
select new Student()
{
Id=int.Parse(element.Attribute("Id").Value),
Name=element.Attribute("Name").Value,
Age=int.Parse(element.Attribute("Age").Value)
};
}
<ListView x:Name="ListViewXml" Margin="276,152,261,239">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" Width="40" DisplayMemberBinding="{Binding Id}"/>
<GridViewColumn Header="Name" Width="60" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Age" Width="60" DisplayMemberBinding="{Binding Age}"/>
</GridView>
</ListView.View>
</ListView>
<Button x:Name="LoadXml2ListView" Content="LoadXml" HorizontalAlignment="Left" Margin="276,289,0,0" VerticalAlignment="Top" Click="LoadXml2ListView_Click"/>
<Button x:Name="SearchXml" Content="SearchXml" HorizontalAlignment="Left" Margin="353,289,0,0" VerticalAlignment="Top" Click="SearchXml_Click"/>
调试时会发现,
通过 doc.Descendants("Student")
,会自动跨越过class,直达Student。遍历Student中每个元素。LINQ是XML中的内容。
3.7 ObjectDataProvider
把对象作为数据源提供给Binding
前面用到过XmlDataProvider
这两个父类都是DataSourceProvider
抽象类
3.8 RelativeSource
已知source与Target在同一个UI,但不知道Source对象名称 - >使用RelativerSource
实操
添加四个Panel,依次嵌套,最内层TextBox和最外层Grid的Name进行绑定
<Grid x:Name="G1" Margin="276,330,350,48" Background="#FFFFC4DA">
<DockPanel x:Name="D1" Margin="10,10,10,10" Background="#FFFFFF">
<Grid x:Name="G2" Margin="10,10,10,10" Background="#00FFC4">
<DockPanel x:Name="D2" Margin="10,10,10,10" Background="AntiqueWhite">
<TextBox x:Name="T1" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Grid},AncestorLevel=1},Path=Name}" FontSize="24" Margin="20,20,20,20" Background="#FF001094" Foreground="#FFE9EAE3" />
</DockPanel>
</Grid>
</DockPanel>
</Grid>
<TextBox x:Name="T1" Text="{Binding RelativeSource=
{RelativeSource
//建立RelativeSource实例Mode=FindAncestor,
//设定模式-查找原型、祖先AncestorType={x:Type Grid},
//祖先的类型 – 控件的类型?AncestorLevel=1},Path=Name}"
//查找深度,设定对应值和显示名称 1-G1,2-G2,3-MyGrid(最外层)查找属性元素路径:名称
也可以在代码里设置 - 估计需要修改代码适配
总结
binding是对数据的管理,Binding 需要确定 source 和path
————————————————
版权声明:本文为优快云博主「天才小秋的学习日记」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/PikaQQ/article/details/127318456