【问题标题】:INotifyPropertyChanged not working on ObservableCollection propertyINotifyPropertyChanged 不适用于 ObservableCollection 属性
【发布时间】:2009-02-27 12:47:27
【问题描述】:

我有一个名为IssuesView 的类,它实现了INotifyPropertyChanged。这个类拥有一个ObservableCollection<Issue> 并将其公开为一个DependencyProperty,称为问题供Bindings 使用。定义如下-

    public class IssuesView : DependencyObject, INotifyPropertyChanged
{
    public Issues Issues
    {
        get { return (Issues)GetValue(IssuesProperty); }
        set
        {
            SetValue(IssuesProperty, value);
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Issues"));
            }
        }
    }

    // Using a DependencyProperty as the backing store for Issues.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IssuesProperty =
        DependencyProperty.Register("Issues", typeof(Issues), typeof(IssuesView), new UIPropertyMetadata(null));



    public IssuesView()
    {
        Refresh();
    }

    public void Refresh()
    {
        this.Issues = new Issues();
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

我有一个这样声明的测试页面 -

<Page x:Class="Tracker.Pages.DEMO"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:cont="clr-namespace:Tracker.Controls"
Title="DEMO">
<StackPanel>
    <Button Click="Button_Click">Change</Button>
    <cont:IssueTimeline IssuesForTimeline="{Binding Source={StaticResource issuesView},Path = Issues}"/>
</StackPanel>

IssuesView 类在 Application.Resources 中定义。
现在在按钮的事件 hadnler 我有这个代码 -

private void Button_Click(object sender, RoutedEventArgs e)
    {
        IssuesView iv = Application.Current.FindResource("issuesView") as IssuesView;
        if (!once)
        {
            foreach (Issue i in iv.Issues)
            {
                i.DormantFor = new TimeSpan(30, 0, 0, 0);
                i.AssignedUserID = 12;
                i.Name = "MyName";
                i.Priority = Issue.Priorities.Critical;
                i.Status = Issue.Statuses.New;
                i.Summary = "NewSummary";
            }
            once = true;
        }
        else
        {
            iv.Refresh();
        }

once 是一个简单的布尔值,用于测试集合的突变与重新填充。

第一次单击按钮会更改集合的项,并且 UI 会正确更新,因为这些项实现了 INotifyPropertyChanged,但第二次单击会重新填充集合,但不会更新 UI,即使事件不为 null 并且正确触发。

为什么第二次点击时 UI 不更新?我怎样才能使重新填充集合会导致 UI 更新?

【问题讨论】:

  • Ja,applogies。那是个错误。谢谢你的回答,真的很有帮助!

标签: wpf data-binding observablecollection


【解决方案1】:

您确实需要简化您的复制。我可以看出它有几处问题,但如果不查看所有,则无法帮助您解决问题。这是我的简单复制,效果很好。

Window1.xaml:

<Window x:Name="_root" x:Class="CollectionRepro.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 DataContext="{Binding ElementName=_root}">
        <ItemsControl ItemsSource="{Binding Issues}"/>
        <Button x:Name="_addButton">Add</Button>
        <Button x:Name="_resetButton">Reset</Button>
    </StackPanel>
</Window>

Window1.xaml.cs:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;

namespace CollectionRepro
{
    public partial class Window1 : Window
    {
        public static readonly DependencyProperty IssuesProperty = DependencyProperty.Register("Issues",
            typeof(ICollection<string>),
            typeof(Window1));

        public ICollection<string> Issues
        {
            get { return (ICollection<string>)GetValue(IssuesProperty); }
            set { SetValue(IssuesProperty, value); }
        }

        public Window1()
        {
            InitializeComponent();
            Reset();

            _addButton.Click +=new RoutedEventHandler(_addButton_Click);
            _resetButton.Click += new RoutedEventHandler(_resetButton_Click);
        }

        void  _resetButton_Click(object sender, RoutedEventArgs e)
        {
            Reset();
        }

        void  _addButton_Click(object sender, RoutedEventArgs e)
        {
            Issues.Add("Another issue");
        }

        private void Reset()
        {
            Issues = new ObservableCollection<string>();
        }
    }
}

【讨论】:

    【解决方案2】:

    首先:没有理由实现为 DependencyProperties 更改的 INotifyProperty。 DependencyProperties 知道它们何时发生变化。

    第二:我在你的代码中没有看到ObservableCollection

    第三:我并不完全清楚(从您发布的代码中)您在第一次点击中修改的问题来自哪里。我假设来自另一个动作,未在此处发布。

    如果我假设您想通过第二次单击清除问题列表,我是否正确(因为我不知道 Issues 构造函数的作用)?

    【讨论】:

      猜你喜欢
      • 2021-05-15
      • 1970-01-01
      • 1970-01-01
      • 2011-11-21
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 2013-05-26
      • 2011-12-17
      相关资源
      最近更新 更多