首页 > 解决方案 > 使用 MVVM 获取在 MPF 中选中的复选框项目

问题描述

我目前正在尝试在一长串复选框项目上实现 ctrl 和 shift 选择功能。现在,您可以通过单击列表中的名称突出显示/选择项目,并且可以使用 ctrl 或 shift 选择组。但是,这不会影响复选框。如果选择中的项目已被选中/取消选中,我想通过选中/取消选中所有选定项目来允许组复选框切换。

这意味着尝试检索已选中/未选中的项目并比较其 IsSelected 属性。

这篇文章是我能找到的最接近我正在寻找的东西。

这是我现在拥有的 xaml:

<ListView Name="LeftListView"
          Grid.Row="4" Grid.Column="1"
          ItemsSource="{Binding CvsLeftListView}">

    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
        </Style>
    </ListView.ItemContainerStyle>

    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel Orientation="Vertical"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>

    <ListView.ItemTemplate>
        <DataTemplate>
            <VirtualizingStackPanel Orientation="Horizontal">
                <CheckBox Name="LeftListCheckBox"
                          IsChecked="{Binding Path=IsChecked, Mode=TwoWay}"
                          Command="{Binding Path=DataContext.CheckBoxChanged, RelativeSource={RelativeSource AncestorType=ListView}}"
                          Checked="LeftListCheckBox_Checked" Unchecked="LeftListCheckBox_Unchecked"/>
                <TextBlock Name="LeftListName"
                           Text="{Binding Name}"
                           Margin="2,0,0,0"/>
            </VirtualizingStackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

以及部分对象类供参考:

public class MyObject : ObservableObject
{
    // Fields
    private string _id;
    private string _fullName;
    private string _name;

    private bool _isChecked;
    private bool _isVisible;
    private bool _isSelected;

    #region Constructors

    #region Properties
}

标签: c#wpfcheckboxmvvm

解决方案


我最终为列表中的每个对象附加了一个事件侦听器。每当调用它时,它都会检查 a) 复选框是否已更改,b) 项目是否被选中/突出显示,以及 c) 项目是否可见。如果所有这些都满足,那么它将更改所有其他选定/突出显示的项目的复选框。

这是 ViewModel 中的代码。我在构造函数中将此侦听器添加到对象的 PropertyChanged 事件中。

private void MyObject_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    MyObject modifiedItem = sender as MyObject;

    if (e.PropertyName == "IsChecked" && modifiedItem.IsVisible && modifiedItem.IsSelected)
    {
        if (this.LeftListViewDisplayList.Contains(modifiedItem))
        {
            this.PropagateCheck(this._cvsLeftListView, this.LeftListViewDisplayList, modifiedItem.IsChecked);
        }
    }
}

private void PropagateCheck(ICollectionView displayedCollection, ObservableCollection<MyObject> storedCollection, bool checkValue)
{
    List<int> _groupIndices = new List<int>(displayedCollection.Cast<MyObject>().Count());

    foreach (MyObject item in displayedCollection)
    {
        if (item.IsSelected)
        {
            _groupIndices.Add(storedCollection.IndexOf(item));
            item.IsSelected = false;
            item.IsChecked = checkValue;
        }
    }

    foreach (int i in _groupIndices)
    {
        storedCollection[i].IsSelected = true;
    }

    displayedCollection.Refresh();
}

推荐阅读