简体   繁体   English

Wpf CheckedListbox - 如何获取所选项目

[英]Wpf CheckedListbox - how to get selected item

I've made a CheckedListbox in xaml using this code:我使用以下代码在 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>

And its bind to this collection:它绑定到这个集合:

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

The CheckedListItem class looks like this: 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"));
        }
    }
}

I tried to set a breakpoint in the _selectedSection = value;我试图在 _selectedSection = value; 中设置断点; part of the code but it never gets triggered when i select/deselect an item in the CheckedListBox.代码的一部分,但是当我在 CheckedListBox 中选择/取消选择一个项目时,它永远不会被触发。

My question is how can I get the selected item every time its selected/deselected ?我的问题是如何在每次选择/取消选择时获取所选项目?

Thanks谢谢

Change your XAML to将您的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>

You are probably clicking on the actual textblock control inside the checkbox or the square control which doesn't trigger selectionchanged for a listbox .您可能正在单击checkbox内的实际textblock控件或不会触发listbox selectionchangedsquare控件。 If you try to click outside the bounds of the rectangle say the whitespace then it will fire.如果您尝试在矩形边界外单击,请说whitespace然后它会触发。

It'll be more work if you just want the checkbox as the datatemplate since you want to select/deselect listboxitem ' based on the checkbox IsChecked property.如果您只想将checkbox作为数据模板,那将会有更多的工作,因为您想根据checkbox IsChecked属性选择/取消选择listboxitem '。 So just wrap it inside a ListBoxItem and you should be good to go.因此,只需将它包装在ListBoxItem ,您就可以开始使用了。

My solution (based on Suplanus and lll solutions above):我的解决方案(基于上面的Suplanuslll解决方案):

<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>

I set ListBoxItem IsSelected property througt style (because standard lll's way not work well)!我设置了 ListBoxItem IsSelected 属性 througt 样式(因为标准lll 的方式不能很好地工作)! In this case, when CheckBox is checked ListBoxItem is selected and vice versa.在这种情况下,当 CheckBox 被选中时 ListBoxItem 被选中,反之亦然。 SelectionMode in this case also works well.在这种情况下,SelectionMode 也能很好地工作。 You can add SelectedItem (or similar property) in Single SelectionMode您可以在 Single SelectionMode 中添加 SelectedItem(或类似属性)

<!-- xaml -->
SelectedItem="{Binding SelectedCheckbox}" SelectionMode="Single"
// cs
public CheckboxData SelectedCheckbox { get; set; }

or maybe even better, work directly with ItemsSource (Checkboxes collection in this case) in behind code (your ViewModel for example).或者甚至更好,直接在后台代码(例如您的 ViewModel)中使用 ItemsSource(在这种情况下为 Checkboxes 集合)。

Behind code (for example):后面的代码(例如):

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>();
}

Note:笔记:
If you want change Checkboxes collection (or selected item) from behind code (and reflect changes in UI) you have to implement INotifyPropertyChanged and notify when collection (or selected item) has been changed (literally, when object has been re created).如果您想从代码后面更改 Checkboxes 集合(或选定项)(并反映 UI 中的更改),您必须实现INotifyPropertyChanged并在集合(或选定项)更改时(字面意思是重新创建对象时)通知。

I think the better solution is to not declare in a ListboxItem, because the selection on Hover is shown on the Checkbox.我认为更好的解决方案是不在 ListboxItem 中声明,因为 Hover 上的选择显示在 Checkbox 上。

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

I found the following solution to work:我找到了以下解决方案:

<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>

I was binding to a Dictionary<string, MyEnum> and none of the solutions above worked.我绑定到 Dictionary<string, MyEnum> 并且上述解决方案都不起作用。 Taking a cue from a question about ListView with checked items , I was able to come up with the following that seems to act like one would hope - including being able to get the selected items from lstMyEnumTypes.SelectedItems.一个关于 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM