WPF:获取一个ListBoxItem作为CheckBox,使用模板样式与IsSelected同步

本文关键字:样式 同步 IsSelected CheckBox 作为 获取 ListBoxItem 一个 WPF | 更新日期: 2023-09-27 18:01:25

我正在制作一个MVVM WPF应用程序,在这个应用程序中,我有一个带有我自己的特权项的列表框。

经过多年,我终于找到了一个解决方案,如何让选择与我的ViewModel同步。(你还需要在你的item类中实现IEquatable)

现在我想样式的ListBoxItems作为复选框,有很多解决这个问题,但没有一个真正符合我的需要。

所以我想出了这个解决方案,因为我可以将这种风格只应用于我需要的ListBoxes,而且我不必担心DisplayMemberPath或项目被样式为CheckBox ListBoxItems。

视图:

<ListBox Grid.Row="5" Grid.Column="1"
         ItemsSource="{Binding Privileges}"
         BehavExt:SelectedItems.Items="{Binding SelectedPrivileges}"
         SelectionMode="Multiple"
         DisplayMemberPath="Name"
         Style="{StaticResource CheckBoxListBox}"/>

风格:

<Style x:Key="CheckBoxListBox"
       TargetType="{x:Type ListBox}"
       BasedOn="{StaticResource MetroListBox}">
    <Setter Property="Margin" Value="5" />
    <Setter Property="ItemContainerStyle"
            Value="{DynamicResource CheckBoxListBoxItem}" />
</Style>
<Style x:Key="CheckBoxListBoxItem"
       TargetType="{x:Type ListBoxItem}"
       BasedOn="{StaticResource MetroListBoxItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <CheckBox IsChecked="{TemplateBinding Property=IsSelected}">
                    <ContentPresenter />
                </CheckBox>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

ViewModel:

private ObservableCollection<Privilege> _privileges;
public ObservableCollection<Privilege> Privileges
{
    get { return _privileges; }
    set {
        _privileges = value;
        RaisePropertyChanged(() => Privileges);
    }
}
private ObservableCollection<Privilege> _selectedPrivileges;
public ObservableCollection<Privilege> SelectedPrivileges
{
    get { return _selectedPrivileges; }
    set
    {
        _selectedPrivileges = value;
        RaisePropertyChanged(() => SelectedPrivileges);
    }
}

问题出在这一行:

IsChecked="{TemplateBinding Property=IsSelected}"

它工作得很好,但只在一个方向上。当在代码中添加一个项目到我的SelectedPrivileges时,它将显示为选中,但是当我在GUI中选中这个项目时,它不会做任何事情。(没有CheckBox样式,它可以工作,所以这是因为TemplateBinding只在一个方向上工作)

我怎么让它工作?我考虑过类似触发器的东西,但我不知道如何实现这一点。

WPF:获取一个ListBoxItem作为CheckBox,使用模板样式与IsSelected同步

我相信你要找的其实很简单。您需要更改IsChecked属性的绑定模式,如下所示:

{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected, Mode=TwoWay}

应该可以了。

这个和基本上任何其他WPF绑定技巧都可以在这个优秀的小抄中找到。