是否有简洁的方法在ViewModel中定义C#WPF中的数据绑定属性?以下属性定义非常详细,尤其是当存在大量属性时:
private bool mSomeProperty;
public bool SomeProperty
{
get { return this.mSomeProperty; }
set
{
if (value != this.mSomeProperty)
{
this.mSomeProperty = value;
OnPropertyChanged(new PropertyChangedEventArgs("SomeProperty"));
}
}
}
答案 0 :(得分:3)
在C#中,我喜欢创建一个基类并在其上放置一些辅助方法。然后我让我的ViewModels从它下降。这是来自记忆,但它是这样的:
public class Observable : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void SetProperty<T>(ref T backingField, T newValue,
string propertyName)
{
if (Equals(backingField, newValue))
return;
backingField = newValue;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
并且,在使用中:
public class MyClass : Observable
{
private bool m_someProperty;
public bool SomeProperty
{
get { return m_someProperty; }
set { SetProperty(ref m_someProperty, value, "SomeProperty"); }
}
}
答案 1 :(得分:2)
您可以在这里找到一些想法:
实施和使用INotifyPropertyChanged https://github.com/jbe2277/waf/wiki/Implementing-and-usage-of-INotifyPropertyChanged
答案 2 :(得分:1)
你总是可以使用DependencyProperties并且支持你的心......
答案 3 :(得分:0)
如果您使用的是Delphi Prism语言(基于Pascal的.NET语言),只需添加notify
关键字,编译器会自动实现INotifyPropertyChanged并为您编写所有样板代码:
property SomeProperty: bool; notify;
答案 4 :(得分:0)
我认为你不会得到比这更小的财产声明,至少不是“正常”的方式。您可以使用城堡拦截器来处理事件raisal。
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChanged;
public void FirePropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(propertyName);
}
public virtual string MyProperty { get; set; }
public virtual string MyProperty2 { get; set; }
}
拦截器需要触发属性更改事件:
public class PropertyChangedInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
//Pseudo code
if (invocation.Method is Property Setter)
{
Call FirePropertyChanged of invocation.InvocationTarget ;
}
}
}
您只需要确保您的视图模型的属性是虚拟的,并且您的视图模型始终是代理,而不是视图模型本身。
最好的问候
答案 5 :(得分:0)
您可以考虑PostSharp,它允许您装饰属性(然后您可以将其重新定义为自动属性)并将引发NotifyPropertyChanged事件的行注入到setter中。一个额外的好处是你摆脱了与属性名称相同的字符串。
这并不理想,因为你需要这个工具,如果你以后看代码就不会立即明白,但它肯定会让它更整洁。
我希望MSFT能够为C#4添加这样的属性,但我想我们必须等待C#5才能完成。
答案 6 :(得分:0)
这个答案与上面的Joe White的答案非常相似,但是代码有点麻烦,并且可能更易于维护,因为属性名称不必作为带引号的字符串传递。
使用 CallerMemberName 功能,有两种方法可以执行此操作。一种方法是创建一个包含 IPropertyNotifyChanged 代码的抽象类,另一种方法是在实际的类中包含 IPropertyNotifyChanged 支持代码。通常,我会根据上下文同时使用两者。
这是使用抽象类时的结果:
public abstract class PropertyNotifier: INotifyPropertyChanged
{
#region INotifyPropertyChanged support code
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T storage, T value,
[CallerMemberName] String propertyName = null)
{
bool result = false;
if (!Object.Equals(storage, value))
{
storage = value;
OnPropertyChanged(propertyName);
result = true;
}
return result;
}
#endregion INotifyPropertyChanged support code
}
使用:
public interface IPerson
{
String FirstName { get; set }
String LastName { get; set }
}
public class Person : PropertyNotifier, IPerson
{
private string _FirstName;
private string _LastName;
public String FirstName
{
get { return _FirstName; }
set { SetProperty(ref _FirstName, value); }
}
public String LastName
{
get { return _LastName; }
set { SetProperty(ref _LastName, value); }
}
}
希望这会有所帮助!