【问题标题】:WPF databinding: how is detected an item change?WPF 数据绑定:如何检测到项目更改?
【发布时间】:2011-08-01 08:16:25
【问题描述】:

我对 WPF 数据绑定有一些问题,我希望在我的解释中清楚,因为我担心这个问题非常微妙。

我基本上有一个带有一堆 ComboBox 的 WPF UserControl,每个 ComboBox 都相互链接。我的意思是第一个组合框填充了一些元素,当用户选择和项目时,第二个组合框根据之前的选择填充元素,以此类推其他组合框。 所有组合框都与 UpdateSourceTrigger=LostFocus 绑定。

组合的 ItemsSource 属性的代码如下所示:

    private ICollectionView allTicketTypesView;
    public IEnumerable<TicketTypeBase> AllTicketTypes
    {
        get { return this.allTicketTypesView.SourceCollection.Cast<TicketTypeBase>(); }
        private set
        {
            IEnumerable<TicketTypeBase> enumerable = value ?? new TicketTypeBase[0];
            ObservableCollection<TicketTypeBase> source = new ObservableCollection<TicketTypeBase>(enumerable);
            this.allTicketTypesView = CollectionViewSource.GetDefaultView(source);
            this.OnPropertyChanged("AllTicketTypes");
        }
    }

组合的 SelectedItem 属性的代码与以下代码类似:

private TicketTypeBase ticketType;
public TicketTypeBase TicketType
{
    get { return this.ticketType; }
    set
    {
        this.ticketType = value;
        this.OnPropertyChanged("TicketType");
        this.UpdateConcessions();
    }
}    

我遇到了一个微妙的问题: 当我用键盘和/或鼠标在我的组合上移动时,我发现当我实际上没有更改列表中的任何项目时,也经常调用 propertychanged。 我的意思是一个组合填充了元素,并选择了一个项目:使用键盘移动组合触发属性更改(并让另一个组合被更新,这是一种不合时宜的行为),但元素本身是相同的. 我在与字符串列表绑定的组合框中看到了这种行为(所以我认为 Equals/GetHashCode 实现没有错误)并且这种行为每次都会发生,除了第一次。

我已经用这个修复了代码:

    private string category;
    public string Category
    {
        get { return this.category; }
        set
        {
            bool actuallyChanged = !String.Equals(this.category, value);
            this.category = value;
            this.OnPropertyChanged("Category");

            if (!actuallyChanged)
            {
                string format = String.Format("Category '{0}' isn't changed actually", value);
                Trace.WriteLine(format);
            }
            else this.UpdateTicketTypes():
        }
    }

但我当然不喜欢这种为设置器添加逻辑的代码。

关于如何避免这种行为的任何建议? 我希望清楚,如果有人不清楚,我准备更好地解释我的问题。

【问题讨论】:

    标签: wpf data-binding


    【解决方案1】:

    您的模型检查属性设置器中使用的值是否实际上与当前值不同并不是不合理的。然而,更“标准”的实现如下所示:

    private string category;
    public string Category
    {
        get { return this.category; }
        set
        {
            // check this is a new value
            if(Object.Equals(this.category, value))
                return;
    
            // set the value
            this.category = value;
            // raise change notification
            this.OnPropertyChanged("Category");
            // compute related changes
            this.UpdateTicketTypes():
        }
    }
    

    【讨论】:

    • 感谢您的回复:但是在第一次之后每次都会发生这种行为让我抓狂:-)
    【解决方案2】:

    只是一个猜测,但您可以实现 SelectedValue 绑定而不是 SelectedItem 吗? SelectedValue(对于 int、string、bool 等值类型)不会在键盘或鼠标焦点上刷新,即使 ItemsSource(带有 CollectionView)发生更改,因为源(或模型)中的更改通知不会触发,因为值类型不会更改参考。

    【讨论】:

    • 看起来没什么变化,但也许我错过了关于 SelectedItem/SelectedValue 差异的一些东西
    猜你喜欢
    • 2011-01-09
    • 2015-11-22
    • 2010-10-24
    • 2010-09-25
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多