如何在不闪烁的情况下更新ComboBox ItemsSource

时间:2018-05-21 19:08:02

标签: c# wpf mvvm

我正在努力应对以前有效的ComboBox更新。我最初将ItemsSource绑定到ViewModel中的只读ObservableCollection<char>属性。当用户发起更改时(使用鼠标笔划进行更改,在某些情况下每秒执行几十次),get会从模型重建集合并返回它。

当我在ObservableCollection中更改为我自己的对象时,ComboBox在更新期间开始闪烁。我不确定出了什么问题。这是从XAML开始的代码:

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

视图模型:

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;
    }
}

如果我在工作代码ViewModel中将char换成BinItem,我会在移动鼠标时闪烁。这是更新的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每次都触发并返回正确的项目集合,界面也不会始终更新(尽管闪烁消失)。 - 在项目源中保留所有可能的bin,并向我绑定的BinItem类添加Visibility属性(无法让它更新)。

我怀疑我做的事情根本就是错误的,但到目前为止,没有多少搜索SO或其他方面的帮助。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

我能够使用克莱门斯和克里斯的想法来解决这个问题。不确定这是否是最优雅的解决方案,但它按预期工作,没有可衡量的性能影响。

我没有用每次刷新替换集合,而是通过找出更改内容的逻辑(每次更新都可以同时添加和删除)。代码如下:

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;
    }
}

希望这也可以帮助其他人。