gpt4 book ai didi

.net - WPF:绑定(bind)到 ListBoxItem.IsSelected 不适用于屏幕外项目

转载 作者:行者123 更新时间:2023-12-04 05:57:16 24 4
gpt4 key购买 nike

在我的程序中,我有一组 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));
}
}

可以观察到两个不同的问题。
  • 如果单击第一个项目,然后按 Shift+End,则应选择所有 200 个项目;但是,标题报告只选择了 21 个项目。
  • 如果单击“全选”,则确实选择了所有项目。如果您然后单击 ListBox 中的一个项目,您会希望取消选择其他 199 个项目,但这不会发生。相反,只有屏幕上的项目(以及其他一些项目)被取消选择。除非您首先从头到尾滚动列表,否则所有 199 个项目都不会被取消选择(即使这样,奇怪的是,如果您使用小滚动框执行滚动,它也不起作用)。

  • 我的问题是:
  • 有人可以准确解释为什么会发生这种情况吗?
  • 我可以避免或解决这个问题吗?
  • 最佳答案

    ListBox默认情况下,UI 是虚拟化的。这意味着在任何给定时刻,ItemsSource 中只有可见项目(以及“几乎可见”项目的一小部分子集)。实际会被渲染。这就解释了为什么更新源可以按预期工作(因为这些项目总是存在的),但只是导航 UI 不能(因为这些项目的视觉表示是动态创建和销毁的,并且永远不会同时存在。)

    如果您想关闭此行为,一个选项是设置 ScrollViewer.CanContentScroll=False在您的 ListBox 上.这将启用“平滑”滚动,并隐式关闭虚拟化。要显式禁用虚拟化,您可以设置 VirtualizingStackPanel.IsVirtualizing=False .

    关于.net - WPF:绑定(bind)到 ListBoxItem.IsSelected 不适用于屏幕外项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7097999/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com