一种在C#WPF中定义MVVM数据绑定属性的简明方法

时间:2009-08-28 17:01:00

标签: c# wpf mvvm data-binding

是否有简洁的方法在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"));
        }
    }
}

7 个答案:

答案 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); }
    }
}

希望这会有所帮助!