【问题标题】:Why are listbox items not being unselected if they are not in view, after the listbox itself comes back into view?如果列表框本身不在视图中,为什么列表框项目不会被取消选择?
【发布时间】:2022-10-15 03:45:50
【问题描述】:

这是我在 MVVM 项目中发现的一个奇怪问题。我将 ListBoxItem 的 IsSelected 属性绑定到基础模型中的 IsSelected 属性。如果包含绑定到列表的模型的集合太大,当您选择不同的用户控件并且焦点从 ListBox 移开时;当您在列表中选择一个项目时,它将取消选择每个项目,但屏幕外的项目除外。下面的 gif 显示了我专门为这个问题制作的一个测试项目中的这个问题;

主视图.xaml

<UserControl x:Class="ListBox_Selection_Issue.Views.MainView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ListBox_Selection_Issue.Views"
             xmlns:vms="clr-namespace:ListBox_Selection_Issue.ViewModels"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.DataContext>
        <vms:MainViewModel/>
    </UserControl.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <ListBox Grid.Row="0" SelectionMode="Extended" ItemsSource="{Binding FirstCollection}">
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <Button Grid.Row="1"/>
    </Grid>
</UserControl>

主视图模型.cs

using System.Collections.ObjectModel;

namespace ListBox_Selection_Issue.ViewModels
{
    class MainViewModel : ObservableObject
    {
        private ObservableCollection<CustomClass> _firstCollection;
        public ObservableCollection<CustomClass> FirstCollection
        {
            get { return _firstCollection; }
            set
            {
                _firstCollection = value;
                OnPropertyChanged("FirstCollection");
            }
        }

        public MainViewModel()
        {
            ObservableCollection<CustomClass> first = new ObservableCollection<CustomClass>();

            for (int i = 1; i <= 300; i++)
            {
                first.Add(new CustomClass($"{i}"));
            }

            FirstCollection = first;
        }
    }

    public class CustomClass
    {
        public string Name { get; set; }
        public bool IsSelected { get; set; }

        public CustomClass(string name)
        {
            Name = name;
            IsSelected = false;
        }
    }
}

【问题讨论】:

    标签: c# wpf mvvm listbox


    【解决方案1】:

    找到解决这个问题的时间比我预期的要长,所以我想我会分享我的知识。

    将VirtualizingStackPanel.IsVirtualizing="False" 添加到 ListBox 中,如下文件所示:

    <UserControl x:Class="ListBox_Selection_Issue.Views.MainView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:ListBox_Selection_Issue.Views"
                 xmlns:vms="clr-namespace:ListBox_Selection_Issue.ViewModels"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
        <UserControl.DataContext>
            <vms:MainViewModel/>
        </UserControl.DataContext>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
    
            <ListBox Grid.Row="0" SelectionMode="Extended" VirtualizingStackPanel.IsVirtualizing="False" ItemsSource="{Binding FirstCollection}">
                <ListBox.ItemContainerStyle>
                    <Style TargetType="{x:Type ListBoxItem}">
                        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                    </Style>
                </ListBox.ItemContainerStyle>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Name}" />
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
    
            <Button Grid.Row="1"/>
        </Grid>
    </UserControl>
    

    我发现这个问题与this answer 的“虚拟化”有关(选择显示更多 cmets)。然后我开始研究列表框虚拟化。我丢失了我从中得到答案的标签。所以,我不能相信他们。希望这将有助于将来的某人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-23
      相关资源
      最近更新 更多