如果数据绑定控件不可见,则不应更新

时间:2011-05-04 23:10:03

标签: wpf data-binding

我有一个WPF应用程序,设计遵循标准的MVVM模型。

当基础数据发生变化时,我的视图模型会触发PropertyChanged事件,以便控件可以更新。

我的主视图是一个制表符控件,因此大多数控件在任何时候都是不可见的。存在性能问题,我意识到大部分CPU时间专用于获取数据以更新不可见控件。 (我的视图模型使用延迟评估,因此它会触发PropertyChanged事件,但在询问之前实际上并不计算最终的可显示属性。)

WPF是否有标准的方法来处理这个问题?

理想情况下,如果一个不可见的控件收到一个相关的PropertyChanged事件,它应该只是想“我必须重新查询该属性一旦我再次可见”。

3 个答案:

答案 0 :(得分:1)

我认为没有任何基础设施来处理与不可见控件关联的停用绑定。不幸的是,在许多情况下,您需要一个不可见的控件参与数据绑定。最重要的是,您经常拥有一个控件,其可见性本身取决于绑定。此外,您可能在可见控件的属性和不可见的控件之间具有绑定。或者有人可能想要与您想要的完全相反:控件在不可见时填充自身,然后在可见时跳出完全填充。

我认为对你的情况唯一的好解决方案是避免使用重量级的不可见控件,如果可能的话。特别是对于您的选项卡控件,我原以为这将是默认行为,但也许这取决于您的情况。具有讽刺意味的是,有些人抱怨TabControl在标签之间切换时会破坏它的孩子,并想知道如何防止这种情况,因为保留内存中的所有背景标签需要一些工作。但你似乎有相反的问题。

供参考,以下是我为TabControl孩子提到的来源:

您可以在一个小项目中进行一些实验,以“打开”他们试图关闭的回收行为。如果您的控件是按需加载的,那么选项卡切换可能会慢一点,但选项卡上的性能会提高。

答案 1 :(得分:1)

我们在基础ViewModel中沿着这些行做了一些事情。

注意,您必须冻结/解冻与View的可见性相对应。

它基本上会在冻结时捕获所有PropertyChanged事件,并在解冻时将它们推出。虽然也没有保持欺骗,但在我们的案例中它们并不重要。

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private readonly HashSet<string> hashSet = new HashSet<string>();
    private bool isFrozen;

    protected void RaisePropertyChanged(string propertyName)
    {
        if (isFrozen)
        {
            lock (hashSet)
            {
                hashSet.Add(propertyName);
                return;
            }
        }

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected void Freeze()
    {
        isFrozen = true;
    }

    /// <summary>
    /// Enable PropertyChanged Events to fire again
    /// </summary>
    protected void Thaw(bool fireQueued)
    {
        isFrozen = false;
        if (fireQueued)
        {
            lock (hashSet)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    foreach (string propertyName in hashSet)
                    {
                        handler(this, new PropertyChangedEventArgs(propertyName));
                    }
                }

                hashSet.Clear();
            }
        }
        else
        {
            hashSet.Clear();
        }
    }
}

答案 2 :(得分:0)

我的基本视图模型具有IsVisible属性。当视图模型不可见时,只需抑制属性更改通知。当它变得可见时,触发每个属性的属性更改事件(pr将null传递给属性名称)