Элементы управления с привязкой к данным не должны обновляться, если они не видны - PullRequest
9 голосов
/ 05 мая 2011

У меня есть приложение WPF, и дизайн соответствует стандартной модели MVVM.

Когда базовые данные изменяются, моя модель представления запускает событие PropertyChanged , чтобы элементы управления могли обновляться.

Мой основной вид - это элемент управления вкладками, поэтому большинство элементов управления невидимы одновременно. Есть проблемы с производительностью, и я понял, что большая часть процессорного времени уходит на выборку данных для обновления невидимых элементов управления. (Моя модель представления использует ленивую оценку, поэтому она запускает события PropertyChanged, но фактически не вычисляет окончательные отображаемые свойства, пока не будет задан вопрос).

Есть ли у WPF стандартный способ решения этой проблемы?

В идеале, если невидимый элемент управления получает соответствующее событие PropertyChanged, он должен просто подумать: «Я должен запросить это свойство , как только я снова буду видим ».

Ответы [ 3 ]

1 голос
/ 13 октября 2011

Мы сделали что-то в этом духе в нашей базовой 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();
        }
    }
}
1 голос
/ 05 мая 2011

Я не думаю, что есть какая-либо инфраструктура для обработки деактивирующих привязок, связанных с невидимыми элементами управления.К сожалению, есть много ситуаций, в которых вы хотели бы, чтобы элемент управления не был виден для участия в привязке данных.Самое главное, у вас часто есть элемент управления, видимость которого зависит от привязки.Кроме того, у вас может быть связь между свойствами видимого элемента управления и невидимого элемента управления.Или кому-то может понадобиться полная противоположность того, что вы хотите: элемент управления заполняется сам, пока невидим, а затем выскакивает полностью заполненным, когда он виден.

Я думаю, что единственное хорошее решение для вашей ситуации - это избегать тяжеловесаневидимые элементы управления, если это возможно.Специально для управления вкладками я бы подумал, что это будет поведение по умолчанию, но, возможно, это зависит от вашей ситуации.По иронии судьбы некоторые люди жалуются на то, что TabControl уничтожает своих дочерних элементов при переключении между вкладками, и хотели бы знать, как этого избежать, потому что сохранение всех фоновых вкладок в памяти требует некоторой работы.Но, похоже, у вас возникла противоположная проблема.

Для справки, вот источник, который я упомянул для TabControl children:

Возможно, вам удастся провести несколько экспериментов в небольшом проекте, чтобы "включить" режим утилизации, который они пытаются отключить.Если ваш элемент управления загружался по требованию, переключение между вкладками могло бы быть немного медленнее, но производительность вкладки могла бы улучшиться.

0 голосов
/ 13 октября 2011

Моя базовая модель просмотра имеет свойство IsVisible.Когда модель представления невидима, просто подавляйте уведомления об изменениях свойств.Когда он становится видимым, происходит отключение свойства, измененного для каждого свойства (передайте значение null в имя свойства)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...