Как обновить ComboBox ItemsSource без мерцания - PullRequest
0 голосов
/ 21 мая 2018

Я борюсь с обновлением до ComboBox, которое ранее работало.У меня изначально ItemsSource была привязана только для чтения ObservableCollection<char> свойство в ViewModel.Когда пользователь инициирует изменения (что делается с помощью движений мыши, в некоторых случаях десятки раз в секунду), метод get перестраивает коллекцию из модели и возвращает ее.

Когда я изменил свой собственный объект вObservableCollection, ComboBox начал мигать во время обновлений.Я не уверен, что происходит не так.Вот код, который работает, начиная с XAML:

<ComboBox ItemsSource='{Binding FromBins}' SelectedValue='{Binding SelectedFromBin, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}' />

ViewModel:

public ObservableCollection<char> FromBins
    {
        get
        {
            ObservableCollection<char> tempBins = new ObservableCollection<char>();
            foreach (var item in Map.BinCounts)
            {
                tempBins.Add(item.Key);
            }
            return tempBins;
        }
    }

Я просто поднимаю изменение свойства при каждом движении мыши, и интерфейс работает, как и ожидалось (естьнекоторая другая логика, обеспечивающая правильность SelectedItem.

Чтобы сделать интерфейс более полезным, я решил добавить дополнительную информацию к ComboBox, используя свой собственный класс:

public class BinItem : IEquatable<BinItem>
{
    public char Bin { get; set; }
    public SolidColorBrush BinColor { get; set; }
    public string BinColorToolTip { get {...} }

    public BinItem( char bin )
    {
        Bin = bin;
        BinColor = new SolidColorBrush(BinColors.GetBinColor(bin));
    }

    public bool Equals(BinItem other)
    {
        return other.Bin == Bin ? true : false;
    }
}

Если я поменяю char на BinItem в рабочем коде ViewModel, я получу мерцание при перемещении мыши.Вот обновленный XAML:

<ComboBox ItemsSource='{Binding FromBins}' SelectedValue='{Binding SelectedFromBin, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}'>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" ToolTip='{Binding BinColorToolTip}'>
                <Rectangle Fill='{Binding BinColor}' Width='10' Height='10' HorizontalAlignment='Center' VerticalAlignment='Center' Margin='0,0,4,0' Stroke='#FF747474' />
                    <TextBlock Text="{Binding Bin}" Width='16' />
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Я перепробовал множество вещей, включая, но не ограничиваясь: -Использование List вместо ObservableCollection, но даже если Get срабатывает каждый раз ивозвращает правильный набор элементов, интерфейс не всегда обновляется (хотя мерцание исчезает).Оставив все возможные ячейки в источнике элементов и добавив свойство Visibility к классу BinItem, к которому я привязан (не удалось его обновить).

Я подозреваю, что делаю что-то в корне неверное, ноникакое количество поиска ТАК или иначе не помогло до сих пор.Любая помощь приветствуется.

1 Ответ

0 голосов
/ 22 мая 2018

Мне удалось решить это, используя идеи Клеменса и Криса.Не уверен, что это самое элегантное решение, но оно работает так, как задумано, без ощутимого снижения производительности.

Вместо замены коллекции при каждом обновлении, я прохожу логику выяснения того, что изменилось (с каждым обновлением).может быть добавление и удаление одновременно).Код ниже:

private ObservableCollection<BinItem> _FromBins = new ObservableCollection<BinItem>();

public ObservableCollection<BinItem> FromBins
{
    get
    {
        if (_FromBins.Count > 0)
        {
            List<char> BinsToRemove = new List<char>();
            foreach (var item in _FromBins)
            {
                if (!Map.BinCounts.ContainsKey(item.Bin))
                {
                    BinsToRemove.Add(item.Bin);
                }
            } 
            foreach (var item in BinsToRemove)
            {
                _FromBins.Remove(new BinItem(item));
            }
        }
        foreach (var item in Map.BinCounts)
        {
            if (!_FromBins.Contains(new BinItem(item.Key)) && item.Value > 0)                   {
                _FromBins.Add(new BinItem(item.Key));
            }
        }
        return _FromBins;
    }
}

Надеюсь, это может помочь кому-то еще.

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