《深入浅出WPF》笔记二

1、消息驱动与事件驱动

事件 即封装过的消息

2、数据驱动

3、Binding

Source、Target、Path、INotifyPropertyChanged结构

this.textBoxName.SetBinding(TextBox.TextProperty,new Binding("Name){Source=stu=new Student()});

4、把控件作为Binding的Source

<Slider x:Name="slider1" Maximum="100" Minimun="0"/>
<TextBox x:Name="textBox1" Text="{Binding Value,ElementName=slider1}"/>

在C#中一般不必使用ElementName属性,直接将对象赋值给Binding的Source属性即可。 

5、Binding的Mode(数据流向)

TwoWay、OneWay、OnTime、OneWayToSource、Default

6、Binding的UpdateSourceTrigger

PropertyChanged、LostFocus、Explicit、Default

7、Binding的其他属性:NotifyOnSourceUpdated和NotifyOnTargetUpdated,监听激发的事件可以找出有哪些数据或控件被更新了。

8、Binding的Path

<TextBox x:Name="textBox1"/>
<TextBox x:Name="textBox2" Text="{Binding Path=Text.Length,ElementName=textBox1,Mode=OneWay}"/>
<TextBox x:Name="textBox3" Text="{Binding Path=Text[3],ElementName=textBox1,Mode=OneWay}"/>

当使用一个集合或DataView作为Binding源时,如果想把默认元素作为Path使用,则使用如下语法:

1 List<string> stirngList=new List<string>(){"Tim","Tom","Blog"};
2 this.textBox1.SetBinding(TextBox.TextProperty,new Binding("/"){Source=stringList});
3 this.textBox2.SetBinding(TextBox.TextProperty,new Binding("/Length"){Source=stringList});
4 this.textBox3.SetBinding(TextBox.TextProperty,new Binding("/[3]"){Source=stringList});

 如果集合元素的属性仍然是一个集合,想把子集中的元素作为Path,则可以使用多级斜线的语法(类似文件路径的那种,一级一级往下找)。

9、当Binding的Source本身只是数据(string、int等)时,Binding的Path设置为“.”(XAML中可以省略该设置。)

10、为Binding指定Source的几种方法

(1)普通的CLR类型单个对象

如果实现了INotifyPropertyChanged接口,则在set属性时激发PropertyChanged事件来通知Binding数据已更新。

(2)普通CLR集合类型的对象(数组,List<T>,ObservableCollection<T>)

一般把控件的ItemsSource属性使用Binding关联到一个集合对象上。

(3)ADO.NET数据对象(DataTable和DataView等)

<Grid>
    <ListView x:Name="listViewStudents">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}"/>
                <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
                <GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}"/>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>            
1 DataTable dt=this.Load();
2 this.listViewStudents.ItemsSource=dt.DefaultView;

或者

DataTable dt=this.Load();
this.listViewStudents.DataContext=dt;
this.listViewStudents.SetBinding(ListView.ItemsSourceProperty,new Binding());

(4)XmlDataProvider把XML数据指定为Source

可以把树状结构的XML数据作为Source指定给级联控件(TreeView和Menu)的Binding。

使用XML数据作为Binding的Source时,我们使用XPath属性来指定数据的来源,而不是Path属性。

<Window.Resources>
    <XmlDataProvider x:Key="xdp" XPath="FileSystem/Folder">
        <x:Data>
            <FileSystem xmlns="">
                <Folder Name="Books">
                    <Folder Name="Cooks">
                        <Folder Name="Cook1"/>
                        <Folder Name="Cook2"/>
                    </Folder>
                    <Folder Name="Tools">
                        <Folder Name="Tool1"/>
                        <Folder Name="Tool2"/>
                    </Folder>
                </Folder>
            </FileSystem>
        </x:Data>
    </XmlDataProvider>
</Window.Resources>    
<Grid>
    <TreeView ItemsSource="{Binding Source={StaticResouce xdp}}">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding XPath=Folder}">
                <TextBlock Text="{Binding XPath=@Name}"/>
            </HierarchicalDataTemplate >
        </TreeView.ItemTemplate>
    </TreeView>
</Grid>

 (5)依赖对象(Dependency Object)

(6)把容器的DataContext指定为Source

建立一个Binding,只设置Path而不设置Source,该Binding就会沿着控件树一层层往外找,直到找到带有Path指定属性的对象。如果到了控件树根部仍然找不到,那么该Binding就得不到数据。

<StackPanel>
    <StackPanel.DataContext>
        <local:Student Id="1" Age="29" Name="Tim"/>
    </StackPanel.DataContext>
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding Path=Id}"/>
            <TextBox Text="{Binding Path=Name}"/>
            <TextBox Text="{Binding Path=Age}"/>
        </StackPanel>
    </Grid>
</StackPanel>

实际上,DataContext是一个依赖属性,当没有为当前控件的依赖属性显式赋值时,控件就会把自己容器的属性值当做自己的属性值。也就是属性值沿着元素树向下传递了。

当多个控件Binding关注同一个对象时,可以使用DataContext。

将A窗体中的控件或控件的值作为窗体A的DataContext,可以将该控件暴露给其他的窗体。

(7)通过ElementName属性指定Source

(8)RelativeSource

<TextBox Text="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Grid},AncestorLevel=1},Path=Name}"

(9)ObjectDataProvider

用于数据源的数据不是通过属性而是通过方法暴露给外界的时候。

 1 ObjectDataProvider odp=new ObjectDataProvider();
 2 odp.ObjectInstance=new Calculator();
 3 odp.MethodName="Add";
 4 odp.MethodParameters.Add("0");
 5 odp.MethodParameters.Add("0");
 6 
 7 Binding bindingToArg1=new Binding("MethodParameters[0]")
 8 {
 9    Source=odp;
10    BindsDirectlyToSource=true;
11    UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged  
12 };
13 
14 Binding bindingToArg2=new Binding("MethodParameters[1]")
15 {
16    Source=odp;
17    BindsDirectlyToSource=true;
18    UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged  
19 };
20 
21 Binding bindingToResult=new Binding(".")
22 {
23    Source=odp;
24 };
25 
26 this.textBoxArg1.SetBinding(TextBox.TextProperty,bindingToArg1);
27 this.textBoxArg2.SetBinding(TextBox.TextProperty,bindingToArg2);
28 this.textBoxResult.SetBinding(TextBox.TextProperty,bindingToResult);

(10)LINQ检索得到的数据对象作为数据源

从一个填充好的List<Student>对象中检索出所有名字以T开头的学生。

this.listViewStudents.ItemsSource=from stu in stilts where su.Name.StartsWith("T") select stu;

如果数据存放在一个填充好的DataTable对象里:

 1 DataTable dt=this.GetDataTable();
 2 this.listViewStudents.ItemsSource=
 3     from row in dt.Rows.Cast<DataRow>()
 4     where Convert.ToString(row["Name"]).StartsWith("T")
 5     select new Student()
 6     {
 7         Id=int.Parse(row["Id"].ToString()),
 8         Name=row["Name"].ToString(),
 9         Age=int.Parse(row["Age"].ToString())
10     };

 如果数据放在XML文件里:

 1 XDocument xdoc=XDocument.Load(@"D:RawData.xml");
 2 this.listViewStudents.ItemsSource=
 3     from element in xdoc.Descendants("Student")
 4     where element.Attribute("Name").Value.StartsWith("T")
 5     select new Student()
 6     {
 7         Id=int.Parse(element.Attribute("Id").Value);
 8         Name=element.Attribute("Name").Value;
 9         Age=int.Parse(element.Attribute("Age").Value);
10     };

 11、Binding数据验证——ValidationRules

Binding默认认为来自Source的数据总是正确地,若要校验来自Source的数据,需将校验条件的ValidatesOnTargetUpdated属性设置为true。

12、Binding的数据转换——IValueConverter接口

13、多路Binding

用于UI需要显示的信息由不止一个数据来源决定的时候。

比如,新用户注册的时候,用户名输入一致,邮箱输入一致时,注册按钮才可用。

1 MutiBinding mb=new MultiBinding(){Mode=BindingMode.OneWay};
2 mb.Bindings.Add(new Binding("Text"){Source=this.textBox1});
3 mb.Bindings.Add(new Binding("Text"){Source=this.textBox2});
4 mb.Bindings.Add(new Binding("Text"){Source=this.textBox3});
5 mb.Bindings.Add(new Binding("Text"){Source=this.textBox4});
6 mb.Converter=new LoginMultiBindingConverter();
7 
8 this.button1.SetBinding(Button.IsEnabledProperty,mb);

Convert()方法的具体实现:

1 if(!Value.Cast<string>().Any(text=>string.IsNullOrEmpty(text))
2     && values[0].ToString()==values[1].ToString()
3     && values[1].ToString()==values[3].ToString())
4 {
5     return true;
6 }
7 else
8     return false;
原文地址:https://www.cnblogs.com/tt2015-sz/p/4800058.html