《深入浅出WPF》6.0 绑定

数据是编程的核心

6.1 DataBinding重要性

程序三层结构:数据存储、数据处理、数据表示

算法分布:数据库内部、读写数据、业务逻辑、数据展示、界面与逻辑的交互

逻辑层优于展示层的功能支持:DataBinding、DependencyProperty、

DataTemplate

6.2 Binding的实现

定义类:注意要实现接口INotifyPerportyChanged自动通知属性发生变化更新数据,this.PropertyChanged.Invoke调用

public class Studet : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private string name;
    public string Name
    {
        get { return name; }
        set
        {
            name = value;
            if (PropertyChanged != null)
                    {
                        this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
                    }
        }
    }
}

UI编写:

<StackPanel>
    <TextBox x:Name="textbox1"/>
    <Button x:Name="Button1" Content="修改" Width="130" Click="Button1_Click"/>
</StackPanel>

绑定方式1:

//实例化绑定类
Binding binding = new Binding();
binding.Source = studet;
binding.Path = new PropertyPath("Name");
//绑定
BindingOperations.SetBinding(this.textbox1, TextBox.TextProperty, binding);

绑定方式2:

this.textbox1.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = studet = new Studet()});

6.3 绑定源与路径

  • Class对象
  • 自己或自己的容器、子集元素作为源
  • 另一个控件
  • 集合作为ItemsControl源
  • XML作为TreeView或Menu源
  • 多个控件关联到一个数据源
    绑定自己

6.3.1控件作为数据源

XAML中绑定

  <TextBox x:Name="textbox2" Text="{Binding ElementName=Slider1,Path=Value}" BorderBrush="Black"/>
        <Slider x:Name="Slider1"/>

C# 中绑定

   this.textbox3.SetBinding(TextBox.TextProperty, new Binding("Value") { ElementName = "Slider2" });

6.3.2 绑定的方向及数据更新

绑定方向:Mode

数据更新触发方式:UpdateSourceTrigger

  <TextBox x:Name="textbox1" Text="{Binding ElementName=Slider1,Path=Value,Mode=OneWayToSource,UpdateSourceTrigger=PropertyChanged}" />
# 注意
* NotifySourceUpdated设置为TREU会触发SourceUpdated事件
* NofifyTargetUpdated设置为TRUE会触发TargetUpdated事件

6.3.3 绑定的路径Path

绑定支持多级路径

<TextBox x:Name="textbox2" BorderBrush="Black"/>
<TextBox Text="{Binding ElementName=textbox2,Path=Text.Length,Mode=OneWay}"/>
<TextBox Text="{Binding ElementName=textbox2,Path=Text.[3],Mode=OneWay}"/>
<TextBox Text="{Binding ElementName=textbox2,Path=Text[3],Mode=OneWay}"/>

当使用集合元素作为绑定值时,把默认元素当作Path使用,使用斜杠/,可以使用多级斜杠

List<string> StringList = new List<string>() { "Tim", "Tom", "Blog" };
textbox3.SetBinding(TextBox.TextProperty, new Binding("/") { Source = StringList });
textbox4.SetBinding(TextBox.TextProperty, new Binding("/[2]") { Source = StringList,Mode=BindingMode.OneWay });
textbox5.SetBinding(TextBox.TextProperty, new Binding("/Length") { Source = StringList,Mode=BindingMode.OneWay });

6.3.4 没有绑定路径的Path

应用于直接取绑定对象本身的值,Path在XAML中可以不写或者写点号,但是在C#中需要写

<StackPanel>
    <StackPanel.Resources>
        <sys:String x:Key="string1">AAAAA</sys:String>
    </StackPanel.Resources>
    <TextBox x:Name="textbox1" Text="{Binding Path=., Source={StaticResource ResourceKey=string1},Mode=OneWay}"/>
</StackPanel>
string string1 = "ABCDEF";
textbox2.SetBinding(TextBox.TextProperty, new Binding(".") { Source = string1 });

6.3.5 为绑定指定源

绑定源:

  • CLR类型单个对象,如果要实现数据更新通知,要实现INotifyPropertyChanged接口,激发PropertyChanged事件,如Class
  • CLR类型集合,如数组、List
  • ADO.NET数据对象,如Datatable和DataView等
  • XMLDtatprovider提供的XML数据,可应用于TreeView等控件
  • 依赖对象(dependencyProperty)
  • 容器的DataContext
  • XAML通过Element指定
  • 通过Binding的RelativeSource指定
  • ObjectDataProvider
  • LINQ检索

6.3.6 DataContext作为绑定源

每一个WPF控件都拥有DataContext属性,UI元素树每一个节点都拥有该属性

默认没有写绑定Source,那么会默认向根部寻找所有节点的DataContext属性的Path

<StackPanel>
    <StackPanel.DataContext>
        <local:student Age="5" Name="tom" ID="34"/>
    </StackPanel.DataContext>
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding Path=Age}"/>
            <TextBox Text="{Binding Path=Name}"/>
            <TextBox Text="{Binding Path=ID}"/>
        </StackPanel>
    </Grid>
</StackPanel>
# 注意,这个只能向根结点找数据,因为属性值沿着UI元素向下传递,如果内层未设置属性,则属性值会向下传递
<StackPanel DataContext="ABD">
    <StackPanel>
        <Grid>
            <Grid>
                <Grid >
                    <Button Height="50" x:Name="BTN1" Click="BTN1_Click"/>
                </Grid>
            </Grid>
        </Grid>
    </StackPanel>  
</StackPanel>
private void BTN1_Click(object sender, RoutedEventArgs e)
{
    BTN1.Content = BTN1.DataContext;
}

失败案例:

<StackPanel>       
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding Path=Age}"/>
            <TextBox Text="{Binding Path=Name}"/>
            <TextBox Text="{Binding Path=ID}"/>
            <StackPanel>
                <StackPanel.DataContext>
                    <local:student Age="5" Name="tom" ID="34"/>
                </StackPanel.DataContext>
            </StackPanel>
        </StackPanel>          
    </Grid>
</StackPanel>

6.3.7 Itemsource集合对象作为源

ItemsSource属性:设置对象源

DisplayMemberPath属性:设置显示的属性

示例一:

<StackPanel x:Name="stackPanel" Background="LightBlue">
    <TextBlock Text="studentID:" FontWeight="Bold" Margin="5"/>
    <TextBox x:Name="textBoxId" Margin="5"/>
    <TextBlock Text="Stdent List:" FontWeight="Black" Margin="5"/>
    <ListBox x:Name="ListBoxStudents" Height="110" Margin="5"/>
</StackPanel>
public Window6()
{

    InitializeComponent();
    List<student> students = new List<student>()
    {
        new student(){Id=0,Name="Tom",Age=29},
        new student(){Id=1,Name="Tim",Age=28},
        new student(){Id=2,Name="Kyle",Age=27},
        new student(){Id=3,Name="Tony",Age=26},
        new student(){Id=4,Name="Vina",Age=25},
        new student(){Id=5,Name="Mike",Age=24},
    };
    this.ListBoxStudents.ItemsSource = students;
    this.ListBoxStudents.DisplayMemberPath = "Name";

    Binding binding = new Binding("SelectedItem.Id") { Source = this.ListBoxStudents };
    this.textBoxId.SetBinding(TextBox.TextProperty, binding);
}
public class student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}
# 注意其中
* ItemsSource、DisplayMemberPath使用
* SelectedItem.Id的使用

示例二删除DisplayMemberPath属性后,通过模板方式在XAML中使用:

<StackPanel x:Name="stackPanel" Background="LightBlue">
    <TextBlock Text="studentID:" FontWeight="Bold" Margin="5"/>
    <TextBox x:Name="textBoxId" Margin="5"/>
    <TextBlock Text="Stdent List:" FontWeight="Black" Margin="5"/>
    <ListBox x:Name="ListBoxStudents" Height="110" Margin="5">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Id}" Width="30"/>
                    <TextBlock Text="{Binding Path=Name}" Width="60"/>
                    <TextBlock Text="{Binding Path=Age}" Width="30"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>
# 注意
* 一般建议用ObservableCollection替代List,因为继承了INotifyCollectionChanged和INotifyproperChanged

6.3.8使用ADO.net作为源

使用属性:ItemSource、DisplaymemberPath

DataTable dataTable= this.Loadtb();
this.Listbox1.DisplayMemberPath = "Name";
this.Listbox1.ItemsSource = dataTable.DefaultView;

使用ListView

//this.Lisview1.ItemsSource = this.Loadtb().DefaultView;
this.Lisview1.DataContext = this.Loadtb();
this.Lisview1.SetBinding(ListView.ItemsSourceProperty, new Binding());
<StackPanel>
    <ListView x:Name="Lisview1" Height="200" BorderBrush="Black">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Id" DisplayMemberBinding="{Binding Path=Id}" Width="60"/>
                <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}" Width="60"/>
                <GridViewColumn Header="Age" DisplayMemberBinding="{Binding Path=Age}" Width="60"/>
            </GridView>
        </ListView.View>            
    </ListView>
</StackPanel>

6.3.9 使用XML作为绑定源

<Window.Resources>
    <XmlDataProvider x:Key="xdp" XPath="Filesystem/Folder">
        <x:XData>
            <Filesystem xmlns="">
                <Folder Name="Books">
                    <Folder Name="Programming">
                        <Folder Name="Windows">
                            <Folder Name="WPF"/>
                            <Folder Name="MFC"/>
                            <Folder Name="Delphi"/>
                        </Folder>
                    </Folder>
                    <Folder Name="Tools">
                        <Folder Name="Development"/>
                        <Folder Name="Designment"/>
                        <Folder Name="Players"/>
                    </Folder>
                </Folder>    
            </Filesystem>                      
        </x:XData>            
    </XmlDataProvider>
</Window.Resources>
<Grid>
    <TreeView ItemsSource="{Binding Source={StaticResource xdp}}">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding XPath=Folder}">
                <CheckBox  Content="{Binding XPath=@Name}"/>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</Grid>

* 6.3.10 使用LINQ语法检索结果

* 6.3.11使用Objectdataprovider

*6.3.12 RelativeSource UI相对位置控件作为绑定

6.4 Binding数据转换与校验

6.4.1 绑定的数据校验

原文地址:https://www.cnblogs.com/ycccq/p/13491182.html