具有复选框的列表框项目,多选在WPF MVVM中无法正常工作

时间:2017-07-23 21:05:06

标签: c# wpf checkbox mvvm

所以我有一个ListBox CheckBox - es,其IsChecked属性绑定到名为IsSelected的Item属性。这产生了一种奇怪的行为,如果我点击项目本身它会检查复选框(好)并设置项目的属性(好),但实际上并没有选择列表框中的项目,即。突出显示不在那里。我猜这个ListBox IsSelected属性也需要设置好吗? 现在,我正在尝试使多选行为起作用,因此我将SelectionMode更改为Extended。现在,我只能选择项目,而不是复选框。会发生的是,如果我通过指向项目旁边的区域而不是项目本身来使用SHIFT +点击,那么它会选择多个项目,但点击这些项目本身并不能实现多项选择的技巧它会检查复选框。这里发生了什么?

我希望能够通过按住shift等来选择多个项目,然后在Elevation项目上触发该属性,这样我就知道检查了哪些项目。任何帮助表示赞赏。

这是我的XAML:

<ListBox x:Name="LevelsListBox"
                         ItemsSource="{Binding Elevations, UpdateSourceTrigger=PropertyChanged}"
                         SelectionMode="Extended"
                         BorderThickness="0">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding IsSelected}" Content="{Binding Name}"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

我的视图模型:

public class AxoFromElevationViewModel : ViewModelBase
    {
        public AxoFromElevationModel Model { get; }
        public RelayCommand CheckAll { get; }
        public RelayCommand CheckNone { get; }

        public AxoFromElevationViewModel(AxoFromElevationModel model)
        {
            Model = model;
            Elevations = Model.CollectElevations();
            CheckAll = new RelayCommand(OnCheckAll);
            CheckNone = new RelayCommand(OnCheckNone);
        }


        private void OnCheckNone()
        {
            foreach (var e in Elevations)
            {
                e.IsSelected = false;
            }
        }


        private void OnCheckAll()
        {
            foreach (var e in Elevations)
            {
                e.IsSelected = true;
            }
        }

        /// <summary>
        /// All Elevation Wrappers.
        /// </summary>
        private ObservableCollection<ElevationWrapper> _elevations = new ObservableCollection<ElevationWrapper>();
        public ObservableCollection<ElevationWrapper> Elevations
        {
            get { return _elevations; }
            set { _elevations = value; RaisePropertyChanged(() => Elevations); }
        }
    }

最后我的海拔等级:

public sealed class ElevationWrapper : INotifyPropertyChanged
    {
        public string Name { get; set; }
        public ElementId Id { get; set; }
        public object Self { get; set; }

        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set { _isSelected = value; RaisePropertyChanged("IsSelected"); }
        }

        public ElevationWrapper(View v)
        {
            Name = v.Name;
            Id = v.Id;
            Self = v;
            IsSelected = false;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propname)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname));
        }
    }

2 个答案:

答案 0 :(得分:4)

您应该将IsSelected的{​​{1}}属性绑定到视图模型的ListBoxItem属性。这样IsSelected es将触发选择,当您选择项目时,将检查相关的CheckBox

CheckBox

答案 1 :(得分:3)

在我看来,你想同步3个属性ListBoxItem.IsSelected,CheckBox.IsChecked和你的模型IsSelected。 我的建议是只有一个模板/样式应该绑定到底层模型,所以我将添加Yusuf答案,因为我将使用ListBoxItem样式绑定到您的模型属性。 之后你应该将Checkbox.IsChecked绑定到ListBoxItem.IsSelected,你的ListBox应该如下所示:

    <ListBox x:Name="LevelsListBox"
             ItemsSource="{Binding Elevations, UpdateSourceTrigger=PropertyChanged}"
             SelectionMode="Extended"
             BorderThickness="0">
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Content="{Binding Name}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

始终尝试以链式方式绑定XAML属性,例如model.A绑定到Model.B绑定到Model.C,这样做可以帮助您保持更新的一致性并避免出现奇怪的情况。

此代码存在问题,但是在您选择多个项目并单击一个复选框后,它将仅取消选择该项目,但如果您单击另一个项目,它将取消选择除该项目之外的所有项目。