WPF ObservableCollection and PropertyChanged

本文关键字:PropertyChanged and ObservableCollection WPF | 更新日期: 2023-09-27 17:57:01

我有一个关于更新可观察集合的问题。我正在使用Visual Studio 2010 c#。我是一个相对新手,可能犯了一个灾难性的错误,所以很抱歉开始。基本上,当我在Windows 7上运行它时,这段代码可以完美运行,但在Windows 8上,我在PropertyChanged上得到了一个NullReferenceException

我有一个保存任务可观察集合的类。

任务.cs

namespace TimeLocation
{
    public static class TStatic
    {
        static TStatic()
        {
            TaskList = new ObservableCollection<Tasks>(); 
        }
        public static ObservableCollection<Tasks> TaskList { set; get; }
    }

public class Tasks : INotifyPropertyChanged
{
    public int taskID;
    public string taskname;
    public Tasks(string tname)
    {
        this.taskname = tname;
    }

    public string Taskname
    {
        get { return taskname; }
        set
        {
            if (value != "")
            {
                taskname = value; OnPropertyChanged("Taskname");
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(info));
        }
    }
}

我在 MainWindow 中有一个绑定到任务的网格,并且在更新时通过上面的PropertyChanged更新正常。用户还可以通过使用鼠标拖动来编辑任务。我希望这也更新网格和可观察集合。当在Windows 7上运行时,这可以工作,但在Windows 8上失败。

在 mainwindow.xaml 的代码隐藏中

public partial class MainWindow : INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = TStatic.TaskList;
    }
    private void dCanvas_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        Tasks t = _selectedtask;
        t.taskname = "Test";
        PropertyChanged(t, new PropertyChangedEventArgs("Taskname"));
    }
}

我确定任务名称已更新,因为当我将其保存到文件并添加监视时名称已更改。

_selectedtask已填充了选择网格行的任务。

在 Windows 8 中,该行

PropertyChanged(t, new PropertyChangedEventArgs("Taskname"));

返回空错误。在 Windows 7 中,它不为空,并且可以正确更新网格。

WPF ObservableCollection and PropertyChanged

首先,公共字段声明是一种非常糟糕的做法。应将它们设为私有,并在需要时通过公共属性授予对它们的访问权限。

其次,像 Window 这样的 UI 元素不应该实现 INotifyPropertyChanged 接口。您可以为视图模型类实现它(请参阅 MVVM 模式,这是 wpf 应用的推荐方法),或者至少为任务等数据类实现它。

在您的dCanvas_PreviewMouseLeftButtonUp代码中,更新可能不起作用,因为您更新了任务对象的字段,但调用了 MainWindow 的 PropertyChanged 方法。设置 TaskName 属性就足够了:

t.TaskName =  "Test"