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>