zoukankan      html  css  js  c++  java
  • WPF Binding基础

      如果把Binding比作数据的桥梁,那么它的两端分别是Binding的源和目标。数据从哪里来就是源,Binding是架在中间的桥梁,Binding目标是数据要往哪儿去。一般情况下,Binding源是逻辑层的对象,Binding目标是UI层的控件对象,这样,数据就会源源不断通过Binding送达UI层,被UI层展现,也就完成了数据驱动UI的过程。

      数据源是一个对象,一个对象上可能有很多数据,这些数据又通过属性暴露给外界。那么,其中哪个数据是你想通过Binding送达UI的元素呢?换句话说,UI上的元素关心的是哪个属性值的变化,这个属性就称为Binding的路径(Path)。但光有属性还不行----Binding是一种自动机制,当值变化后属性要有能力通知Binding,让Binding把变化传递给UI元素。怎样才能让一个属性具备这种通知Binding值已经变化的能力呢?方法就是在set语句中激发一个PropertyChanged事件。这个事件不需要我们自己声明,我们要做的是让作为数据源的类实现INotifyPropertyChanged接口。当Binding设置了数据源之后,Binding就会自动侦听来自这个接口的PropertyChanged事件。

    <StackPanel>
            <TextBox x:Name="txtName" BorderBrush="Black" Margin="5"></TextBox>
            <Button Content="AddAge" Margin="5" Click="Button_Click"></Button>
        </StackPanel>
    class Student : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private string name;
    
            public string Name
            {
                get { return name; }
                set
                {
                    name = value;
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
                    }
                }
            }
    
        }
    public partial class MainWindow : Window
        {
            Student stu;
            public MainWindow()
            {
                InitializeComponent();
                stu = new Student();
                //准备Binding
                Binding binding = new Binding();
                binding.Source = stu;
                binding.Path = new PropertyPath("Name");
                //使用Binding,连接数据源和Binding目标
                BindingOperations.SetBinding(this.txtName, TextBox.TextProperty, binding);
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                stu.Name += "Name";
            }
        }

    这样,当点击button的时候,改变了stu对象的Name属性,该数据会自动更新到UI,就是TextBox

    原理大致如此,写法却有很多,比如BindingOperations.SetBinding,继承自FrameworkElement的类都封装了该方法

    public BindingExpression SetBinding(DependencyProperty dp, string path);

    所以还可以这样写

    InitializeComponent();
                stu = new Student();
                //准备Binding
                Binding binding = new Binding();
                binding.Source = stu;
                binding.Path = new PropertyPath("Name");
                //使用Binding,连接数据源和Binding目标
                //BindingOperations.SetBinding(this.txtName, TextBox.TextProperty, binding);
                txtName.SetBinding(TextBox.TextProperty, binding);

    既然Binding作为源和目标间数据的桥梁,那么数据也是有方向的,控制Binding数据流向的属性是Mode

    public enum BindingMode
        {
            // 摘要:
            //     导致对源属性或目标属性的更改可自动更新对方。此绑定类型适用于可编辑窗体或其他完全交互式 UI 方案。
            TwoWay = 0,
            //
            // 摘要:
            //     当绑定源(源)更改时,更新绑定目标(目标)属性。如果要绑定的控件为隐式只读控件,则适用此绑定类型。例如,可以绑定到如股市代号之类的源。或者,可能目标属性没有用于进行更改(例如表的数据绑定背景色)的控件接口。如果不需要监视目标属性的更改,则使用
            //     System.Windows.Data.BindingMode.OneWay 绑定模式可避免 System.Windows.Data.BindingMode.TwoWay
            //     绑定模式的系统开销。
            OneWay = 1,
            //
            // 摘要:
            //     当应用程序启动或数据上下文更改时,更新绑定目标。此绑定类型适用于以下情况:使用当前状态的快照适合使用的或数据状态实际为静态的数据。如果要从源属性初始化具有某个值的目标属性,并且事先不知道数据上下文,则也可以使用此绑定类型。实质上,这是
            //     System.Windows.Data.BindingMode.OneWay 绑定的较简单的形式,它在不更改源值的情况下可提供更好的性能。
            OneTime = 2,
            //
            // 摘要:
            //     当目标属性更改时更新源属性。
            OneWayToSource = 3,
            //
            // 摘要:
            //     使用绑定目标的默认 System.Windows.Data.Binding.Mode 值。每个依赖项属性的默认值都不同。一般情况下,用户可编辑控件属性(例如文本框和复选框的属性)默认为双向绑定,而多数其他属性默认为单向绑定。确定依赖项属性绑定在默认情况下是单向还是双向的编程方法是:使用
            //     System.Windows.DependencyProperty.GetMetadata(System.Type) 来获取属性的属性元数据,然后检查
            //     System.Windows.FrameworkPropertyMetadata.BindsTwoWayByDefault 属性的布尔值。
            Default = 4,
        }

    Binding还有另外一个属性来控制何时更新数据,它是UpdateSourceTrigger

    public enum UpdateSourceTrigger
        {
            // 摘要:
            //     绑定目标属性的默认 System.Windows.Data.UpdateSourceTrigger 值。多数依赖项属性的默认值为 System.Windows.Data.UpdateSourceTrigger.PropertyChanged,而
            //     System.Windows.Controls.TextBox.Text 属性的默认值为 System.Windows.Data.UpdateSourceTrigger.LostFocus。
            Default = 0,
            //
            // 摘要:
            //     当绑定目标属性更改时,立即更新绑定源。
            PropertyChanged = 1,
            //
            // 摘要:
            //     当绑定目标元素失去焦点时,更新绑定源。
            LostFocus = 2,
            //
            // 摘要:
            //     仅在调用 System.Windows.Data.BindingExpression.UpdateSource() 方法时更新绑定源。
            Explicit = 3,
        }

    顺便提一句,Binding还有具有NotifyOnSourceUpdate和NotifyOnTargetUpdate两个bool类型的属性,如果设置为true,则当源或目标被更新后Binding会被激发相应的SourceUpdated事件和TargetUpdated事件。实际工作中,我们可以通过监听两个事件来找出有哪些数据或控件被更新了。

    没有Source的Binding——使用DataContext作为Binding的源

    首先创建一个数据源类

    public class Student
        {
            public string Id { get; set; }
            public string Name { get; set; }
            public string Age { get; set; }
        }
    <Window x:Class="BindingSample2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:BindingSample2"
            Title="MainWindow" Height="350" Width="525">
        <StackPanel>
            <StackPanel.DataContext>
                <local:Student Age="22" Name="HuangTao" Id="Hello"></local:Student>
            </StackPanel.DataContext>
            <Grid>
                <StackPanel>
                    <TextBox Text="{Binding Path=Id}" Margin="5"></TextBox>
                    <TextBox Text="{Binding Path=Name}" Margin="5"></TextBox>
                    <TextBox Text="{Binding Path=Age}" Margin="5"></TextBox>
                </StackPanel>
            </Grid>
        </StackPanel>
    </Window>

    这3个TextBox的Binding就会自动向UI元素树的上层去寻找可用的DataContext对象。

    没有Source没有Path的Binding,但源本身就是数据的时候

    <Window x:Class="BindingSample2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:BindingSample2"
            xmlns:sys="clr-namespace:System;assembly=mscorlib"
            Title="MainWindow" Height="350" Width="525">
        <StackPanel>
            <StackPanel.DataContext>
                <!--<local:Student Age="22" Name="HuangTao" Id="Hello"></local:Student>-->
                <sys:String>Hello!</sys:String>
            </StackPanel.DataContext>
            <Grid>
                <StackPanel>
                    <!--<TextBox Text="{Binding Path=Id}" Margin="5"></TextBox>
                    <TextBox Text="{Binding Path=Name}" Margin="5"></TextBox>
                    <TextBox Text="{Binding Path=Age}" Margin="5"></TextBox>-->
                    <TextBlock Text="{Binding}" Margin="5"></TextBlock>
                </StackPanel>
            </Grid>
        </StackPanel>
    </Window>
  • 相关阅读:
    POJ 3630 Phone List/POJ 1056 【字典树】
    HDU 1074 Doing Homework【状态压缩DP】
    POJ 1077 Eight【八数码问题】
    状态压缩 POJ 1185 炮兵阵地【状态压缩DP】
    POJ 1806 Manhattan 2025
    POJ 3667 Hotel【经典的线段树】
    状态压缩 POJ 3254 Corn Fields【dp 状态压缩】
    ZOJ 3468 Dice War【PD求概率】
    POJ 2479 Maximum sum【求两个不重叠的连续子串的最大和】
    POJ 3735 Training little cats【矩阵的快速求幂】
  • 原文地址:https://www.cnblogs.com/HelloMyWorld/p/2909211.html
Copyright © 2011-2022 走看看