如何在WPF应用程序中更新多个可观察集合?

rn0zuynd  于 2023-03-19  发布在  其他
关注(0)|答案(1)|浏览(151)

我编写了一个WPF应用程序,它允许用户添加和查看需要以批处理模式构建的项目文件列表,然后查看每个文件在逐个构建时的运行时进度。为了简单起见,我保留了两个列表视图,一个显示用户添加的项目列表,第二个显示了一个文件正在构建时的构建进度。两个列表视图都被实现为ObservableCollections。第一个列表视图工作正常,我可以看到它在我添加一个文件时得到更新。然而,第二个列表视图只在文件完成后才显示其构建状态,所以我必须等到项目构建完成后才能看到项目状态,这不是我实现它的方式.在代码中,对于第二个列表视图,我将文件的status属性设置为“Running”,然后调用通知属性更改(“status”)以便在列表视图上更新它(以便用户可以知道正在构建该文件),然后运行命令来构建该文件。在构建完成之后,我将文件的status属性更改为“Completed”,然后再次调用NotifyPropertyChanged(“状态”)。不过,正如我所说,我看到状态了(显示为“已完成”)。(对NotifyPropertyChanged(“status”)的第一次调用什么也不做)我希望在我将状态更改为“Running”后运行NotifyPropertyChanged(“status”)后很快更新ListView,任何帮助都将非常感谢。

namespace Names { 
    public partial class MainWindow : Window 
    { 
    public ObservableCollection<projectRecord> records;
    public ObservableCollection<projectStatus> statusrecords;
    public MainWindow()
    {
        InitializeComponent();
        records = new ObservableCollection<projectRecord>();
        statusrecords = new ObservableCollection<projectStatus>();
        listName.ItemsSource = records;//first listview
        statusList.ItemsSource = statusrecords;//second listview
    }

    public class projectRecord : INotifyPropertyChanged
    {
        //some properties
        public string lblProjectName { get; set; }
        
        //some methods 
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }    

    public class projectStatus : INotifyPropertyChanged
    {
        //some properties
        public string status { get; set; }
        
        //some methods 
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    } 

    private void ButtonBuild_Click(object sender, RoutedEventArgs e) 
    {
       //fetch project records one by one
       for(i=0;i<records.Count;i++)
        {
          projectRecordName = records[i].lblProjectName; 

          statusrecords.Add(new projectStatus(projectRecordName));

          statusrecords[i].status = "Running";
          statusrecords[i].NotifyPropertyChanged("status");//this does not updates the list view
         
          BuildProjectFile(projectRecordName);

          statusrecords[i].status = "Completed";
          statusrecords[i].NotifyPropertyChanged("status");//this does updates the list view
        }
    }
}

}

aurhwmvo

aurhwmvo1#

除了我稍后会提到的一些奇怪的事情之外,我认为问题可能是BuildProjectFile是同步的,可能阻塞了线程,阻止了状态文本的更新,将其转换为异步方法可能会有所帮助。
我也做了一些调整。
1.看起来ProjectRecord不需要实现INotifyPropertyChanged,因为您没有使用它,所以我删除了它。
1.在ProjectStatus类中,我将NotifyPropertyChanged方法设置为私有,并将调用转移到Status的setter中,这通常是这样做的,您不希望允许外部代码调用(或忘记调用)NotifyPropertyChanged
下面是代码:

namespace Names { 
    public partial class MainWindow : Window 
    { 
        private readonly ObservableCollection<ProjectRecord> records = new ObservableCollection<ProjectRecord>();
        private readonly ObservableCollection<ProjectStatus> statusrecords = new ObservableCollection<ProjectStatus>();

        public MainWindow()
        {
            InitializeComponent();
            
            listName.ItemsSource = records;
            statusList.ItemsSource = statusrecords;
        }

        public class ProjectRecord
        {
            public string ProjectName { get; set; }
        }    

        public class ProjectStatus : INotifyPropertyChanged
        {
            private string _status;
            public string Status 
            {
                get => _status;
                set {
                    _status = value;
                    NotifyPropertyChanged(nameof(Status));
                }    
            }
            
            public event PropertyChangedEventHandler PropertyChanged;

            private void NotifyPropertyChanged(String propertyName)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        } 

        private async void ButtonBuild_Click(object sender, RoutedEventArgs e) 
        {
            for(i = 0; i < records.Count; i++)
            {
                projectRecordName = records[i].ProjectName; 

                statusrecords.Add(new projectStatus(projectRecordName));

                statusrecords[i].Status = "Running";
                
                await BuildProjectFileAsync(projectRecordName);

                statusrecords[i].Status = "Completed";
            }
        }
    }
}

这个有用吗?

相关问题