我正在努力应对以前有效的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或其他方面的帮助。任何帮助表示赞赏。
答案 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;
}
}
希望这也可以帮助其他人。