propertychangedeventhandler,...PropertyChangedEventHandler PropertyChanged;
很多朋友对于propertychangedeventhandler和...PropertyChangedEventHandler PropertyChanged;不太懂,今天就由小编来为大家分享,希望可以帮助到大家,下面一起来看看吧!
...PropertyChangedEventHandler PropertyChanged;
是事件委托。
所谓“事件委托”,一个事件的本质是一个委托(因为事件是委托类型的)。而委托的好处在于它可以动态调用不同类之间具备相同函数签名(函数参数顺序、类型、个数相同),且函数返回值必须完全相同的函数。我先举一个委托的例子:
namespace A
{
public delegate void Say();//委托
class Dog
{
public void Say()
{
Console.WriteLine("汪汪!");
}
}
class Cat
{
public void Say()
{
Console.WriteLine("喵喵!");
}
}
public class MainTest
{
static void Main(string[] args)
{
Say s= new Say(new Dog().Say);//告诉委托调用Dog类中的Say方法
s+= new Cat().Say;//同时告诉委托调用Cat类中的Say方法
s();
}
}
}
Dog和Cat类毫无联系,但是却可以通过委托连接起来关系,我们说委托具备“跨类调用”函数的特性。
因此,我们再来看一个事件的应用:
public class MyClass
{
public event EventHandler MyEvent= null;//EventHandler是一个系统委托,一般用于定义事件
………………
public void MyMethod()//这是一个引发事件的方法,一旦调用该方法,必然触发事件
{
………………
//引发一个事件!!
MyEvent(this,null);
}
}
主函数中:
MyClass mc= new MyClass();
mc.MyEvent+=new EventHandler(MyEvent_Raised);
………………
static void MyEvent_Raised(object sender, EventArgs e)
{
………………//做你想做的事情
}
事件的实例化是在使用到包含这个事件的实体类时候(比如在主函数需要调用的时候)。通过+=进行实体化;然后当调用实体的MyMethod方法时候,这个方法将引发一个事件,也就是触发了绑定的MyEvent_Raised方法。
如何优雅的实现INotifyPropertyChanged接口
InotifyPropertyChanged接口实现分一下几个步骤:
1、定义了一个类,实现接口,实现了绑定和数据的同步(代码如下)
public class person: IMyPropertyChanged
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if(value!= _name)
{
_name= value;
//when changed,notice
NotifyChanged(Name);
}
}
}
}
public class IMyPropertyChanged: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyChanged(string propertyName)
{
if(PropertyChanged!= null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
2、随着定义的person对象属性越来越多,可能有年纪,毕业院校,爱好,性取向等等等,岂不是要写很多类似以上的重复代码?而且,最要命的是,以上方面采用的是硬代码,很容易编译通过,而却出错,我们要采用强类型才行!(专业性较强,2年内程序员的可能看不懂)
public class IMyPropertyChanged: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyChanged<T>(Expression<Func<T>> propertyName)
{
if(PropertyChanged!= null)
{
var memberExpression= propertyName.Body as MemberExpression;
if(memberExpression!= null)
{
PropertyChanged(this, new PropertyChangedEventArgs(memberExpression.Member.Name));
}
}
}
}
public class person: IMyPropertyChanged
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if(value!= _name)
{
_name= value;
//when changed,notice
NotifyChanged<string>(()=> this.Name);
}
}
}
}
3、我们要封装这个操作,那就定义一个静态类:
public class PropertyChangedBase: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if(this.PropertyChanged!= null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public static class IMyPropertyChangedEX
{
public static void NotifyPropertyChanged<T, TProperty>(this T iMyPropertyChanged,
Expression<Func<T, TProperty>> expression) where T: IMyPropertyChanged
{
var memberExpression= expression.Body as MemberExpression;
if(memberExpression!= null)
{
string propertyName= memberExpression.Member.Name;
iMyPropertyChanged.NotifyPropertyChanged(propertyName);
}
else
throw new NotImplementedException();
}
}
4、在person里面编写绑定的属性的更改通知时,就可以这么写:
public class person: IMyPropertyChanged
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if(value!= _name)
{
_name= value;
//when changed,notice
this.NotifyPropertyChanged(p=> p.Name);---!!!!!!
请问一下:在c#.net wpf里面 ,data 的用法
程序的本质是数据加算法,这一点我们在控制台应用中已经能充分体会到,用户给进一个输入,经过算法的处理,程序会反馈一个输出。在这个过程中,数据处于主导,核心地位。然而,自从GUI程序越来越受人们青睐以来,基于UI的“消息驱动”或者“事件驱动”却将数据放到了被动的地位,在一个GUI程序中,数据总是在等待一个事件的触发后才会被处理,同时等待算法执行完后才能在UI控件上显示。如何在GUI编程中把数据的地位从被动变为主动,让数据回归到程序的核心呢?WPF为我们推出了Data Binding机制。
应用程序会具有三层结构,即数据存储层、数据处理层和数据展示层。Binding机制作用在处理层和展示层之间,Binding就像是一座桥梁,它的两端分别是数据的源(source)和目标(target),数据从哪里来那里就是源,Binding是中间的桥梁,Bingding目标是数据要往那里去。一般情况下,Binding源是逻辑层的对象,目标是UI层的控件对象,这样,数据就会不断的通过Binding送达UI层,被UI层展现,也就完成了数据驱动UI的过程。
在大致了解了Binding的概念后,让我们看一个例子来更形象的了解它。
1、首先创建一个名为Student的类,用这个类作为数据源来使用。Student对象有很多属性,那么那个数据是你想通过Binding送达给UI元素,即UI上的元素最关心的是那个属性值的变化,这个属性就是Binding的路径(Path)但,光有属性还不够,因为Binding是一种自动机制,当值变化后,属性要有能力告诉Binding,让Binding把变化传递给UI元素,这就要在属性的Set语句中激发一个PropertyChanged事件。当为Binding设置了数据源后,Binding就会自动侦听这个事件
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"));
}
}
}
}
当Name属性的值发生变化时PropertyChanged事件就会被激发,Binding接收到这个事件后发现事件的消息告诉它是名为Name的属性发生了值的变化,于是会通知Binding目标端的UI元素显示新的值。
2、XAML界面的呈现,窗体上一个Textbox控件作为Binding目标,一个Button控件是为了触发事件来改变Textbox的Name属性值
<Window x:Class="WPFBindingLearn.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<TextBox x:Name="textBoxName" BorderBrush="Black" Margin="5"/>
<Button Content="Add Age" Margin="5" Click="Button_Click"/>
</StackPanel>
</Grid>
</Window>
3、接下来就是使用Binding将数据源和UI元素连接起来
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.textBoxName, TextBox.TextProperty, binding);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
stu.Name+="Name";
}
}
通过为Binding设置数据源,设定访问路径;通过SetBinding()方法实现数据源和目标的连接。该方法的三个参数:
第一个参数用于指定Binding的目标,本例中为textBoxName
第二个参数用于指定将数据送达到目标的那个属性
第三个参数就是用一个binding实例将数据源和目标关联起来
好了,文章到此结束,希望可以帮助到大家。