WPF 之 Binding 数据驱动UI (INotifyPropertyChanged 向客户端发送属性更改通知,ValidationRule 数据校验, IValueConverter数据转换 )

推荐阅读:
WPF 之 Binding 数据驱动UI—实战 https://blog.csdn.net/litao2/article/details/62218220
WPF 之 Binding 数据驱动UI  https://blog.csdn.net/litao2/article/details/18311991
WPF 使用ValidationRule进行表单数据验证  https://blog.csdn.net/litao2/article/details/56283687

一、Data Binding在WPF中的地位

              DataBinding 把UI元素一一与数据关联上(以数据为中心的星形结构),当数据发生变化后,这些UI元素会同步显示这一变化。

程序的逻辑层就像是一个强有力的引擎一直在运作,用加工好的数据驱动用户界面用文字、图形、动画等形式把数据显示出来,这就是数据驱动UI

 

             DataBinding 比作数据桥梁,那么它的两端分别是Binding的源(Source)和目标(Target)。Binding的源是逻辑层对象,Binding的目标是UI层的控件对象。想象 DataBinding 这座桥梁上铺设了高速公路,我们不但可以控制公路是在源与目标之间双向通行还是某个方向的单行道,还可以控制对数据放行的时机,甚至可以在桥上架设一些 “关卡” 用来转换数据类型检验数据的正确性

绑定DataGrid

 

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

 

            List<Student> liststudent=new List<Student>();
            liststudent.Add(new Student{Name="小张",Age=18});
            liststudent.Add(new Student{Name="小张",Age=20});
            GridList.ItemsSource = liststudent;

 

<DataGrid Height="157" x:Name="GridList"/>

【WPF的MVVM DataGrid用法】 https://blog.csdn.net/litao2/article/details/75969595

 

 

 

深入浅出WPF 实例如下:

 

一:创建简单数据源,并通过 Binding 把它连接到UI元素中。

System.ComponentModel  用于实现组件和控件运行时和设计时行为的类

namespace System.ComponentModel
{
    // 摘要:
    //     向客户端发出某一属性值已更改的通知。
    public interface INotifyPropertyChanged
    {
        // 摘要:
        //     在更改属性值时发生。
        event PropertyChangedEventHandler PropertyChanged;
    }
}

 

方法一:

(1)、创建名为Student 类做为数据源,继承 INotifyPropertyChanged(向客户端发出某一属性已更改通知) 接口,

 

    //数据源
    public class Student:INotifyPropertyChanged
    {
        //属性改变
        public event PropertyChangedEventHandler PropertyChanged;
        private string name;

        public string Name
        {
            get { return name; }
            set { 
                name = value;
                if (this.PropertyChanged != null)
                {
                    //属性发生改变后,通知Binding更改UI (Binding Path=**)
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));                  
                }
            }            
        }
    }

                  当Name属性的值发生变化时 PropertyChanged 事件就会被激活,Binding接收到这个事件后发现事件的消息告诉它是名为Name的属性发生了值得改变,于是就会通知Binding目标端的UI元素显示新的值。

 


(2)、UI设计

 

        <TextBox x:Name="textBoxName" BorderBrush="Black" Margin="5"/>
        <Button Content="Add Age" Margin="5" Click="Button_Click"/>

 

 

(3)、使用Binding 将 数据源和UI连接起来。

 

             数据绑定:

                        System.Windows.Data.Binding
                        System.Windows.Data.BindingOperations

 

        Student stu;
        public Window1()
        {
            InitializeComponent();
            //准备数据源
            stu = new Student();

            //准备Binding
            Binding binding = new Binding();
            binding.Source = stu; //绑定源对象
            binding.Path = new PropertyPath("Name");//绑定源对象 属性路径(Name)

            //使用Binding 连接数据源 与Binding目标
            BindingOperations.SetBinding(this.textBoxName, TextBox.TextProperty, binding);
            //BindingOperations.SetBinding(绑定的绑定目标, 绑定的目标属性, 描述绑定的 System.Windows.Data.BindingBase 对象);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            stu.Name += "Name";
            
        }

 

 

效果:

 

 

 

方法二:

注意也可以将准备数据源、准备Binding、使用Binding 连接数据源 与Binding目标。三合一操作。

 

 //TextBox基类 FrameworkElement对BindingOperations.SetBinding()方法进行了封装
this.textBoxName.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = stu = new Student()});
 //源更改,目标UI也会更改

 

 

方法三:

 

 

        Student4 stu;
        public Window30()
        {
            InitializeComponent();
            stu = new Student4();
            stu.Name = "aaa";
            textBox1.DataContext = stu;
        }

 

<TextBox  Name="textBox1"   Text="{Binding Path=Name}"/>
 

 

 

                              <i:Interaction.Triggers>
                                <i:EventTrigger EventName="MouseLeftButtonDown">
                                    <i:InvokeCommandAction Command="{Binding (DataContext).TreeSelectCommand,
                        RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Page}}" CommandParameter="{Binding Name}"/>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>

 

 

 

 

 

 

 

Binding  数据源路径,

RelativeSource(相对数据源)={查找父级,父级类型是Page}

 

方法四:

<Window x:Class="WpfApplication.Window30"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication"
        Title="Window30" Height="300" Width="300">
    <Grid>
        <Grid.DataContext>
            <local:Student4 Name="aa"/>
        </Grid.DataContext>

        <TextBox  Name="textBox1"   Text="{ Binding Path=Name}"/>
    </Grid>
</Window>

 

二:控件间建立关联

1、将TextBox的Text属性 关联 ScrollBar的Value属性

 

    <StackPanel>
        <ScrollBar x:Name="SB" Orientation="Horizontal" Height="30" 
                   Minimum="1" Maximum="100" LargeChange="1" SmallChange="1"/>
        
        <TextBox x:Name="textbox1" Height="30" BorderBrush="Blue" BorderThickness="2" 
               Text="{Binding Value, ElementName=SB}"/>
        <!--{Binding 元素属性, ElementName=数据绑定操作源(元素名)}-->
    </StackPanel>

c#用法:

            //将label的content属性,绑定SB的Vlaue值
            textbox1.SetBinding(TextBox.TextProperty, new Binding("Value") {ElementName="SB" });

 

2、多个控件数据绑定。DataContext

    <StackPanel DataContext="{Binding ElementName=SB}">
        
        <ScrollBar x:Name="SB" Orientation="Horizontal" Height="30" 
                   Minimum="1" Maximum="100" LargeChange="1" SmallChange="1"/>
        
        <Label x:Name="labelSBThumb" Height="30" BorderBrush="Blue" BorderThickness="2" 
               Content="{Binding Path=Value}"/>
        
        <Button Content="Click" Height="200"  FontSize="{Binding Path=Value}"/>

    </StackPanel>

 

 

 

 

 

3、控制Binding的方向及数据更新(TextBox输入值,ScrollBar的值也会更改)

 

            textbox1.SetBinding(TextBox.TextProperty, 
                new Binding("Value") { ElementName = "SB", 
                    Mode = BindingMode.TwoWay, //数据流动方式为双向
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged //目标属性更改时,立即更新数据源
                });

 

 

 

 

 

 

 

 

三:Binding 的路径(Path):如何在对象上找数据。

binding支持多级路径,通俗讲就是一路 “点” 下去。

1、一个TextBox显示另一个TextBox输入文本的长度。

 

    <StackPanel>
         <TextBox x:Name="textbox1" BorderBrush="Black" Margin="5"/>
        <TextBox x:Name="textbox2" BorderBrush="Black" Margin="5" Text="{Binding Path=Text.Length,ElementName=textbox1,Mode=OneWay}"/>
    </StackPanel>

注意:Mode=OneWay  无法对“System.String”类型的只读属性“Length”进行 TwoWay 或 OneWayToSource 绑定。
c#代码:

 

 

            textbox2.SetBinding(TextBox.TextProperty, 
                new Binding("Text.Length") { Source=this.textbox1,Mode=BindingMode.OneWay});

 

 

 

 

2、一个TextBox显示另一个TextBox文本的第4个字符。

 

            textbox2.SetBinding(TextBox.TextProperty, 
                new Binding("Text.[3]") { Source=this.textbox1,Mode=BindingMode.OneWay});

 

3、将集合或DataView作为Binding的源,把它的默认值当作Path使用

 

            List<string> stringList = new List<string>() { "Litao","Tom","Blog"};
            this.textbox1.SetBinding(TextBox.TextProperty,
                new Binding("/") { Source = stringList });
            this.textbox2.SetBinding(TextBox.TextProperty,
                new Binding("/Length") { Source = stringList,Mode=BindingMode.OneWay })
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
如果在WPF中使用数据绑定时,修改了数据UI没有刷新,可能是由于以下几个原因: 1. 数据属性没有实现通知属性更改机制:在ViewModel中,需要实现INotifyPropertyChanged接口,并在属性值发生改变时触发PropertyChanged事件。确保在设置属性值后调用OnPropertyChanged方法。 ```csharp private string _myProperty; public string MyProperty { get { return _myProperty; } set { _myProperty = value; OnPropertyChanged(nameof(MyProperty)); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } ``` 2. 数据绑定未正确指定路径:确保在XAML中,将绑定的Path属性设置为正确的属性路径。例如,如果要绑定到ViewModel中的MyProperty属性,确保路径设置正确。 ```xml <TextBlock Text="{Binding MyProperty}" /> ``` 3. 数据上下文未正确设置:确保将UI元素的数据上下文设置为ViewModel的实例。这可以通过设置Window或UserControl的DataContext属性来实现。 ```xml <Window.DataContext> <local:MyViewModel /> </Window.DataContext> ``` 4. 数据源未正确初始化或更改:在ViewModel中,确保在构造函数或其他适当的位置初始化或更改绑定的属性。这样可以确保初始值或更改后的值被正确地传递到UI。 ```csharp public MyViewModel() { MyProperty = "Initial Value"; } public void UpdateData() { MyProperty = "New Value"; OnPropertyChanged(nameof(MyProperty)); } ``` 如果以上步骤都正确,并且问题仍然存在,可能是由于其他因素导致,比如数据绑定的Mode设置不正确,或者绑定的数据源发生了异常。可以使用调试工具来检查绑定是否正常工作,例如使用Snoop工具来查看绑定的源和目标对象。 希望这些解决方法能帮助到你!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tiz198183

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值