6.WPF学习 - Binding

系列文章目录

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(控件) DataSourcea,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 目标实现
  1. SliderValue作为MainWindow的属性
  2. 编号1的文本框和Slider控件Binding,双向同步更新(Mode=TwoWay),Slider作为source
  3. Slider控件作为Target,SliderValue作为Source,通过Mode=OneWayToSource,反向更新SliderValue值
  4. 编号2文本框作为Target,SliderValue作为Source,通过OneWay进行Binding,这样同步查看SliderValue的值。
3.2.1.2 初步代码以及问题

一开始参考《WPF深入浅出》,代码如下

  1. 新增SliderValue属性
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler?PropertyChanged;
        public int SliderValue{ get; set; }
  1. 修改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 内容

  1. 新建xml文件,包含了StudentList
  2. 创建ListView控件
  3. 新建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}"
<?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

————————————————
版权声明:本文为CSDN博主「天才小秋的学习日记」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/PikaQQ/article/details/127318456

  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值