在我的程序中,我有一组 View 模型对象来表示 ListBox 中的项目(允许多选)。 viewmodel 有一个 IsSelected 属性,我想将其绑定(bind)到 ListBox,以便在 viewmodel 中而不是在列表框本身中管理选择状态。
但是,显然 ListBox 不维护大多数屏幕外项目的绑定(bind),因此通常 IsSelected 属性未正确同步。这是一些演示问题的代码。第一个 XAML:
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock>Number of selected items: </TextBlock>
<TextBlock Text="{Binding NumItemsSelected}"/>
</StackPanel>
<ListBox ItemsSource="{Binding Items}" Height="200" SelectionMode="Extended">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<Button Name="TestSelectAll" Click="TestSelectAll_Click">Select all</Button>
</StackPanel>
C# 全选处理程序:
private void TestSelectAll_Click(object sender, RoutedEventArgs e)
{
foreach (var item in _dataContext.Items)
item.IsSelected = true;
}
C# View 模型:
public class TestItem : NPCHelper
{
TestDataContext _c;
string _text;
public TestItem(TestDataContext c, string text) { _c = c; _text = text; }
public override string ToString() { return _text; }
bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set {
_isSelected = value;
FirePropertyChanged("IsSelected");
_c.FirePropertyChanged("NumItemsSelected");
}
}
}
public class TestDataContext : NPCHelper
{
public TestDataContext()
{
for (int i = 0; i < 200; i++)
_items.Add(new TestItem(this, i.ToString()));
}
ObservableCollection<TestItem> _items = new ObservableCollection<TestItem>();
public ObservableCollection<TestItem> Items { get { return _items; } }
public int NumItemsSelected { get { return _items.Where(it => it.IsSelected).Count(); } }
}
public class NPCHelper : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void FirePropertyChanged(string prop)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
可以观察到两个不同的问题。
我的问题是:
最佳答案
ListBox
默认情况下,UI 是虚拟化的。这意味着在任何给定时刻,ItemsSource
中只有可见项目(以及“几乎可见”项目的一小部分子集)。实际会被渲染。这就解释了为什么更新源可以按预期工作(因为这些项目总是存在的),但只是导航 UI 不能(因为这些项目的视觉表示是动态创建和销毁的,并且永远不会同时存在。)
如果您想关闭此行为,一个选项是设置 ScrollViewer.CanContentScroll=False
在您的 ListBox
上.这将启用“平滑”滚动,并隐式关闭虚拟化。要显式禁用虚拟化,您可以设置 VirtualizingStackPanel.IsVirtualizing=False
.
关于.net - WPF:绑定(bind)到 ListBoxItem.IsSelected 不适用于屏幕外项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7097999/