【问题标题】:Why does a string INotifyPropertyChanged property update but not a List<string>?为什么字符串 INotifyPropertyChanged 属性更新而不是 List<string>?
【发布时间】:2009-11-21 18:57:32
【问题描述】:

在以下 WPF 应用程序中,当您单击按钮时,为什么 TheTitle TextBlock 更新但 FilesCopied ListBox 不更新?

XAML:

<Window x:Class="TestList3433.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <TextBlock Text="{Binding TheTitle}"/>
        <TextBlock Text="above"/>
        <ListBox ItemsSource="{Binding FilesCopied}"/>
        <TextBlock Text="below"/>

        <Button Content="Add to collection" Click="Button_Click"/>
    </StackPanel>
</Window>

代码隐藏:

using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;

namespace TestList3433
{
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        #region ViewModelProperty: FilesCopied
        private List<string> _filesCopied = new List<string>();
        public List<string> FilesCopied
        {
            get
            {
                return _filesCopied;
            }

            set
            {
                _filesCopied = value;
                OnPropertyChanged("FilesCopied");
            }
        }
        #endregion

        #region ViewModelProperty: TheTitle
        private string _theTitle;
        public string TheTitle
        {
            get
            {
                return _theTitle;
            }

            set
            {
                _theTitle = value;
                OnPropertyChanged("TheTitle");
            }
        }
        #endregion

        public Window1()
        {
            InitializeComponent();
            DataContext = this;

            FilesCopied.Add("test1.txt");
            TheTitle = "This is the title";
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            FilesCopied.Add("test2.txt");
            TheTitle = "title was changed";
        }

        #region INotifiedProperty Block
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}

答案:

谢谢罗伯特,我忘记了 ObservableCollection。答案如下:

将 FilesCopied 块更改为:

#region ViewModelProperty: FilesCopied
private ObservableCollection<string> _filesCopied = new ObservableCollection<string>();
public ObservableCollection<string> FilesCopied
{
    get
    {
        return _filesCopied;
    }

    set
    {
        _filesCopied = value;
        OnPropertyChanged("FilesCopied");
    }
}
#endregion

并添加:

using System.Collections.ObjectModel;

【问题讨论】:

    标签: c# wpf generics data-binding xaml


    【解决方案1】:

    您的变更处理程序在列表的 setter 上;但是您没有调用 setter(更改列表)-您正在将项目添加到现有列表中。有单独的接口(@98​​7654322@/IBindingListView 等)用于处理列表通知。 BindingList&lt;T&gt; 是支持通知的 2.0 列表的合理默认实现。

    在 .NET 3.0 及更高版本中,另请参阅 INotifyCollectionChangedObservableCollection&lt;T&gt;

    国际海事组织:

        private readonly ObservableCollection<string> filesCopied =
                new ObservableCollection<string>();
        public ObservableCollection<string> FilesCopied {
            get { return filesCopied; }
        }
    

    【讨论】:

      【解决方案2】:

      因为它没有实现 IBindingList(View),因此 UI 永远不会知道您将任何新内容放入列表中。

      使用 BindingList 或 ObservableCollection。

      【讨论】:

        猜你喜欢
        • 2010-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-01
        • 2021-03-01
        • 1970-01-01
        相关资源
        最近更新 更多