WPF CheckedListbox - как получить выбранный элемент

Я сделал CheckedListbox в xaml, используя этот код:

                    <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 = value; часть кода, но он никогда не запускается, когда я выбираю / отменяю выбор элемента в CheckedListBox.

мой вопрос в том, как я могу получить выбранный элемент каждый раз, когда он выбран / отменен ?

спасибо

4 ответов


изменить XAML to

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

вы, вероятно, нажав на фактический textblock внутри checkbox или square контроль, который не вызывает selectionchanged на listbox. Если вы попытаетесь щелкнуть за пределами прямоугольника, скажите whitespace затем он будет стрелять.

это будет больше работы, если вы просто хотите checkbox как datatemplate, так как вы хотите выбрать/отменить выбор на checkbox этот флажок установлен собственность. Так просто оберните его внутри ListBoxItem и вы должны быть хорошо идти.


Я думаю, что лучшее решение - не объявлять в ListboxItem, потому что выбор при наведении отображается на флажке.

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

мое решение (на основе 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 througt style (потому что standard lll способ не работает)! В этом случае, когда флажок установлен, выбирается ListBoxItem и наоборот. SelectionMode в этом случае также работает хорошо. Вы можете добавить SelectedItem (или аналогичное свойство) в Single SelectionMode

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

или, может быть, даже лучше, работает напрямую с ItemsSource (коллекция флажков в этом случае) в коде позади (например, ваш 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>();
}

Примечание:
Если вы хотите изменить коллекцию флажков (или выбранный элемент) из-за кода (и отразить изменения в пользовательском интерфейсе), вы должны реализовать INotifyPropertyChanged и уведомлять, когда коллекция (или выбранный элемент) была изменена (буквально, когда объект был повторно создан.)


Я нашел следующее решение для работы:

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