数据绑定方法
在使用集合类型作为列表控件的ItemsSource时一般会考虑使用ObservalbeCollection
在使用自定义类型作为界面的数据源时,自定义类型需要自己实现INotifyPropertyChanged接口,一般会把INotifyPropertyChanged接口的实现放到一个基类中。
BindableBase基类
下面的BindableBase类来自Prism,代码如下:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Runtime.CompilerServices;/// <summary>/// 实现 <see cref="INotifyPropertyChanged"/>/// </summary>public abstract class BindableBase : INotifyPropertyChanged{ /// <summary> /// 属性值更改时发生 /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 检查属性是否已与设置值相等,设置属性并仅在必要时通知侦听器。 /// </summary> /// <typeparam name="T">属性的类型</typeparam> /// <param name="storage">对同时具有getter和setter的属性的引用</param> /// <param name="value">属性的所需值</param> /// <param name="propertyName">用于通知侦听器的属性的名称,此值是可选的,从支持CallerMemberName的编译器调用时可以自动提供。</param> /// <returns>如果值已更改,则为True;如果现有值与所需值匹配,则为false。</returns> protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer<T>.Default.Equals(storage, value)) return false; storage = value; RaisePropertyChanged(propertyName); return true; } /// <summary> /// 检查属性是否已与设置值相等,设置属性并仅在必要时通知侦听器。 /// </summary> /// <typeparam name="T">属性的类型</typeparam> /// <param name="storage">对同时具有getter和setter的属性的引用</param> /// <param name="value">属性的所需值</param> /// <param name="propertyName">用于通知侦听器的属性的名称,此值是可选的,从支持CallerMemberName的编译器调用时可以自动提供。</param> /// <param name="onChanged">属性值更改后调用的操作。</param> /// <returns>如果值已更改,则为True;如果现有值与所需值匹配,则为false。</returns> protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null) { if (EqualityComparer<T>.Default.Equals(storage, value)) return false; storage = value; onChanged?.Invoke(); RaisePropertyChanged(propertyName); return true; } /// <summary> /// 引发此对象的PropertyChanged事件。 /// <param name="propertyName">用于通知侦听器的属性的名称,此值是可选的,从支持CallerMemberName的编译器调用时可以自动提供。</param> protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) { OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); } /// <summary> /// 引发此对象的PropertyChanged事件。 /// </summary> /// <param name="args">PropertyChangedEventArgs参数</param> protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) { PropertyChanged?.Invoke(this, args); }}
上面的代码有两点需要注意:
使用EqualityComparer
.Default 属性创建通用比较,而不是使用Object.Equals()。Default属性检查类型T是否实现System.IEquatable(Of T)接口,如果是,则返回使用该实现的EqualityComparer(Of T)。否则,它返回一个EqualityComparer(Of T),它使用T提供的Object.Equals和Object.GetHashCode的替代。使用CallerMemberName特性代替常规的属性名称(也可以使用nameof()运算符关键字来传递属性名称),CallerMemberNameAttribute 类允许获取方法调用方的方法或属性名称,而不必使用字符串文字、 慢速反射代码、复杂的表达式树逻辑或代码编织。
使用BindableBase
实现一个StudentViewModel类(继承BindableBase),代码如下
class StudentViewModel : BindableBase{ private int _id; public int Id { get { return _id; } set { SetProperty(ref _id, value); } } private string _name; public string Name { get { return _name; } set { SetProperty(ref _name, value,new Action(()=> { Id++; })); } } private int _age; public int Age { get { return _age; } set { SetProperty(ref _age, value,nameof(this.Age)); } }}
主界面的XAML代码如下:
<StackPanel x:Name="stack" Background="LightBlue"> <StackPanel.DataContext> <local:StudentViewModel Id="6" Age="29" Name="Tim"/> </StackPanel.DataContext> <Grid> <StackPanel> <TextBox Text="{Binding Path=Id}" Margin="5"/> <TextBox Text="{Binding Path=Name}" Margin="5"/> <TextBox Text="{Binding Path=Age}" Margin="5"/> <Button Content="Age+" Click="Button_Click"/> </StackPanel> </Grid></StackPanel>
主界面的后台实现Button_Click,代码如下:
private void Button_Click(object sender, RoutedEventArgs e){ ((StudentViewModel)this.stack.DataContext).Age ++;}
运行程序,查看数据绑定的效果:
参考资料
PrismLibrary/Prism/BindableBase.cs
INotifyPropertyChanged,.NET 4.6方式
MVVM模式解析和在WPF中的实现(二)数据绑定
原文转载:http://www.shaoqun.com/a/723767.html
agora:https://www.ikjzd.com/w/2176
asinseed:https://www.ikjzd.com/w/533
在使用自定义类型作为界面的数据源时,自定义类型需要自己实现INotifyPropertyChanged接口,一般会把INotifyPropertyChanged接口的实现放到一个基类中。数据绑定方法在使用集合类型作为列表控件的ItemsSource时一般会考虑使用ObservalbeCollection,它实现了INotifyCollectionChanged和INotifyPropertyCha
深兰科技:https://www.ikjzd.com/w/1517
cares:https://www.ikjzd.com/w/1302
f2c:https://www.ikjzd.com/w/1242
速卖通如何打造爆款?:https://www.ikjzd.com/home/113859
Facebook加密货币Libra或无缘印度市场?:https://www.ikjzd.com/home/99011
联邦快递起诉美国商务部,被美国司法部驳回!:https://www.ikjzd.com/home/107413
No comments:
Post a Comment