I have a listview populated with checkboxes in a wpf application.
I am storing the "checked" values in a config file and each time the program is opened, I want to read those values and preselect them in the listview. How do I do this?
XML
<ListView ItemsSource="{Binding ClassificationTypes}" SelectionMode="Multiple" ItemContainerStyle="{StaticResource CheckListView}" SelectionChanged="OnClassification_SelectionChanged" />
StaticResource XML
<Style x:Key="CheckListView" TargetType="ListViewItem">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<CheckBox Margin="5,2" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected, Mode=TwoWay}">
<ContentPresenter />
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Code Behind
I'm populating the list with the enum values.
public ObservableCollection<string> ClassificationTypes { get; set; }
ClassificationTypes = new ObservableCollection<string>();
IEnumerable<ClassTypes> types = Enum.GetValues(typeof(ClassTypes)).Cast<ClassTypes>();
foreach (ClassTypes type in types)
{
string description = EnumExtensions.GetDescription(type);
ClassificationTypes.Add(description);
}
When I start the program, it reads in the configuration file, but at this time, the ListView.Items.Count
is 0, so I cannot loop through them. It is only after the Initialization is complete that it starts pulling all of the bound data to display. How would I preselect certain values before displaying?
You could have a view model with a data item class with a string and a bool property. Depending on your exact requirements you may have to add the usual INotifyPropertyChanged implementation.
public class DataItem
{
public string Text { get; set; }
public bool Selected { get; set; }
}
public class ViewModel
{
public ObservableCollection<DataItem> Items { get; }
= new ObservableCollection<DataItem>();
}
Use it with a ListBox like shown below. Do not use the more complex ListView control when you do not set its View
property.
<ListBox ItemsSource="{Binding Items}" SelectionMode="Multiple">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Selected}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<CheckBox Margin="5,2"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Content="{Binding Text}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Some test data:
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
vm.Items.Add(new DataItem { Text = "Unclassified", Selected = false });
vm.Items.Add(new DataItem { Text = "Human", Selected = true });
vm.Items.Add(new DataItem { Text = "Small Vehicle", Selected = false });
vm.Items.Add(new DataItem { Text = "Large Vehicle", Selected = true });
vm.Items.Add(new DataItem { Text = "Drone", Selected = false });
vm.Items.Add(new DataItem { Text = "Small Airplane", Selected = true });
vm.Items.Add(new DataItem { Text = "Large Airplane", Selected = false });
DataContext = vm;
}