• 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>
  • 相关阅读:
    转载:从git仓库中删除不必要的文件
    问题:Swiper父容器隐藏时实例化组件,组件滑动失效
    图片预加载
    移动端苹果手机:图片没有加载完成前,白色边框线是怎么来的
    bower 安装依赖提示 EINVRES Request to https://bower.herokuapp.com/packages/xxx failed with 502
    H5序列帧播放
    盟军敢死队
    二维游戏开发的点滴
    用c语言开发游戏 快乐的痛 笑着哭
    ibatis
  • 原文地址:https://www.cnblogs.com/HelloMyWorld/p/2909211.html
Copyright © 2020-2023  润新知