【问题标题】:Properties don't get the NotifyPropertyChanged属性没有得到 NotifyPropertyChanged
【发布时间】:2014-11-01 21:57:09
【问题描述】:

我有一个包含 3 个文件的小应用程序。第一个文件是Authentication,它继承自第二个文件ObservableObject。此文件继承INotifyPropertyChanged

class Authentication : ObservableObject
{
    public void Start()
    {
        Auth = Visibility.Visible;
        Tab = Visibility.Collapsed;
    }

    public void SetView()
    {
        Auth = Visibility.Collapsed;
        Tab = Visibility.Visible;
    }

    public Visibility Auth { get; set; }
    public Visibility Tab { get; set; }
    public Visibility Admin { get; set; }
    public Visibility Planner { get; set; }
    public Visibility WorkPrep { get; set; }
    public Visibility Leader { get; set; }
    public Visibility PreSet { get; set; }
    public Visibility Measure { get; set; }
    public Visibility Worker { get; set; }
}

我的第三个文件是我的 View 的 ViewModel。

class MainWindowViewModel : ObservableObject
{
    private Authentication auth = new Authentication();

    public MainWindowViewModel()
    {
        LogIn = new RelayCommand(() => auth.SetView(), () => (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Password)) ? false : true);
        auth.Start();
    }

    public ICommand LogIn { get; set; }
    public Visibility Auth
    {
        get
        {
            return auth.Auth;
        }
        set
        {
            auth.Auth = value;
            NotifyPropertyChanged();
        }
    }
    public Visibility Tab
    {
        get
        {
            return auth.Tab;
        }
        set
        {
            auth.Tab = value;
            NotifyPropertyChanged();
        }
    }
}

现在,当我启动应用程序时,auth.Start(); 被正确执行并设置了正确的Visibility。当我按下绑定到Command LogInButton 时,auth.SetView(); 被执行但Visibilities 没有更新。

我的结论是,当我加载应用程序时,Visibilities 设置正确,但一旦加载,它就不会从 Authentication 类更新为 MainWindowViewModel 类。


编辑:这是对这个问题可能很重要的 ObservableObject 类。

public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

【问题讨论】:

  • 您是否通过调试代码验证了您的结论?
  • @DanielKelley,是的。我检查了每个起作用的变量和属性。当我从public MainWindowViewModel 调用auth.Start(); 时,Visibilities 设置正确。当我从 LogIn Command 调用 auth.SetView() (或常规按钮单击,没关系)时,Authentication 类中的 2 个属性已设置,但 MainWindowViewModel 类中没有设置,它使用的值来自Authentication.
  • @DanielKelley,只是想知道。只做MainWindowViewModel 中的视觉内容和Authentication 中的逻辑内容会更“聪明”吗?然后使用Authentication 中的事件(任何其他选项)直接设置MainWindowViewModel 中的属性?我知道如果我在应用程序运行时在MainWindowViewModel 中设置属性,它会起作用。

标签: c# binding inotifypropertychanged


【解决方案1】:

您通过 Authentication 类更新 Auth 的可见性,这不会导致 NotifyProperty 事件被触发。我在 Authentication 类中添加了对 NotifyPropertyChanged 方法的调用:

class Authentication : ObservableObject
{
    public void Start()
    {
        Auth = Visibility.Visible;
        Tab = Visibility.Collapsed;
    }

    public void SetView()
    {
        Auth = Visibility.Collapsed;
        Tab = Visibility.Visible;
    }

    private Visibility auth;
    public Visibility Auth
    {
        get
        {
            return auth;
        }
        set
        {
            auth= value;
            NotifyPropertyChanged();
        }
    }

    private Visibility tab;
    public Visibility Tab
    {
        get
        {
            return tab;
        }
        set
        {
            tab = value;
            NotifyPropertyChanged();
        }
    }
    // etc
}

现在,我们只是在 MainWindowViewModel 中回显每个 NotifyProperty 事件(在这种情况下应该足够了)。

class MainWindowViewModel : ObservableObject
{
    private Authentication auth = new Authentication();

    public MainWindowViewModel()
    {
        LogIn = new RelayCommand(() => auth.SetView(), () => (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Password)) ? false : true);

        // Echo the PropertyChanged events from our auth class
        auth.PropertyChanged += (sender, e) =>
        {
            if (PropertyChanged != null)
                PropertyChanged(sender, e);
        }

        auth.Start();
    }

    public ICommand LogIn { get; set; }
    public Visibility Auth
    {
        get
        {
            return auth.Auth;
        }
        set
        {
            auth.Auth = value;
            NotifyPropertyChanged();
        }
    }
    public Visibility Tab
    {
        get
        {
            return auth.Tab;
        }
        set
        {
            auth.Tab = value;
            NotifyPropertyChanged();
        }
    }
}

【讨论】:

  • 我在原始帖子中添加了我的ObservableObject 代码。您的建议是正确的,但在这种情况下不是问题。
  • 是的,就是这样!您基本上没有为它提供属性名称(因此默认值propertyName = ""),这使它根本不起作用。将Auth 的实现更改为我建议的,它应该可以正常工作。
  • 在我开始争论之前,你最好检查一下我的代码INotifyPropertyChanged。它使用来自System.Runtime.CompilerServices[CallerMemberName]。这将获取属性的名称并填写它,而无需在调用该方法时输入属性的名称。 CallerMemberName它的描述如下:Allows you to obtain the method or property name of the caller to the method.
  • 我的错,我完全忽略了这一点。但是,嘿,我现在可能发现了问题,检查我更新的答案。如果我错了纠正我。 :)
  • Tnx 回复。明天我会检查它并告诉你进展如何。
猜你喜欢
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-18
  • 2016-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多