Wpf CheckedListbox - 如何获取所选项目

时间:2014-01-17 18:31:03

标签: c# wpf xaml

我使用以下代码在xaml中创建了一个CheckedListbox:

                    <ListBox Height="340" ItemsSource="{Binding Sections}" SelectedItem="{Binding SelectedSection}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Item}" />
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

它与这个集合的绑定:

public ObservableCollection<CheckedListItem<String>> Sections { get; set; }
private CheckedListItem<String> _selectedSection;
public CheckedListItem<String> SelectedSection
    {
        get { return _selectedSection; }
        set 
        {
            _selectedSection = value; 
            RaisePropertyChanged("SelectedSection"); 
        }
    }

CheckedListItem类如下所示:

    public class CheckedListItem<T> : INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler PropertyChanged;

    private bool isChecked;
    private T item;

    public CheckedListItem()
    { }

    public CheckedListItem(T item, bool isChecked = false)
    {
        this.item = item;
        this.isChecked = isChecked;
    }

    public T Item
    {
        get { return item; }
        set
        {
            item = value;
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Item"));
        }
    }


    public bool IsChecked
    {
        get { return isChecked; }
        set
        {
            isChecked = value;
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
        }
    }
}

我试图在_selectedSection =值中设置断点;代码的一部分,但是当我选中/取消选中CheckedListBox中的项目时,它永远不会被触发。

我的问题是如何在每次选择/取消选择时获取所选项目?

由于

5 个答案:

答案 0 :(得分:8)

XAML更改为

<ListBox Height="340" ItemsSource="{Binding Sections}" SelectedItem="{Binding SelectedSection}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <ListBoxItem IsSelected="{Binding IsChecked}">
                <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Item}" />
            </ListBoxItem>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

您可能点击了textblockcheckbox控件中的实际square控件,但selectionchanged没有触发listbox。如果您尝试在矩形的边界外单击,请说whitespace,然后它将触发。

如果您只想将checkbox作为数据模板,那将是更多的工作,因为您要根据listboxitem IsChecked checkbox' >财产。所以只需将其包裹在ListBoxItem内,你应该好好去。

答案 1 :(得分:3)

我的解决方案(基于 Suplanus lll 以上解决方案):

<ListBox ItemsSource="{Binding Checkboxes}" SelectionMode="Multiple">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsSelected" Value="{Binding Checked, Mode=TwoWay}" />
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox IsChecked="{Binding Checked, Mode=TwoWay}" Content="{Binding Label}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我通过样式设置ListBoxItem IsSelected属性(因为标准 lll&#39; s 方式不能正常工作)!在这种情况下,当选中CheckBox时,选择ListBoxItem,反之亦然。在这种情况下,SelectionMode也很有效。您可以在Single SelectionMode

中添加SelectedItem(或类似属性)
<!-- xaml -->
SelectedItem="{Binding SelectedCheckbox}" SelectionMode="Single"
// cs
public CheckboxData SelectedCheckbox { get; set; }

或者甚至更好,直接使用后面代码中的ItemsSource(在这种情况下为Checkboxes集合)(例如,您的ViewModel)。

代码背后(例如):

public partial class MainWindow : Window
{
    public class CheckboxData
    {
        public int Id { get; set; }
        public string Label { get; set; }
        public bool Checked { get; set; }
    }

    public MainWindow()
    {
        DataContext = this;
        for (int i = 0; i < 50; i++)
            Checkboxes.Add(new CheckboxData { Id = i, Label = $"Checkbox {i}" });
    }

    public IList<CheckboxData> Checkboxes { get; set; } = new List<CheckboxData>();
}

注意:
如果您想从后面的代码更改Checkboxes集合(或选定的项目)(并反映UI中的更改),您必须实现 INotifyPropertyChanged 并在集合(或选定项目)更改时通知(字面意思,当对象时)已被重新创建。)

答案 2 :(得分:2)

我认为更好的解决方案是不在ListboxItem中声明,因为Hover上的选择显示在Checkbox上。

 <ListBox ItemsSource="{Binding Customers}" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Item.Name}" /> 
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox> 

答案 3 :(得分:0)

我找到了以下解决方案:

<ListBox Height="340" ItemsSource="{Binding Sections}" SelectedItem="{Binding SelectedSection}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <CheckBox Content="{Binding Path=Item}" IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

答案 4 :(得分:0)

我绑定到 Dictionary 并且上述解决方案均无效。从 a question about ListView with checked items 那里得到提示,我能够想出以下似乎符合人们希望的行为 - 包括能够从 lstMyEnumTypes.SelectedItems 中获取所选项目。

<ListBox x:Name="lstMyEnumTypes" Grid.Row="1" MinHeight="100" VerticalAlignment="Stretch" ItemsSource="{Binding MyEnumsDict}"
  SelectedValuePath="Value" SelectionMode="Multiple">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <CheckBox IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}"
        Content="{Binding Path=Key}"/>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>