Search code examples
c#wpflistview

WPF Listview preselect Checkboxes in code behind


I have a listview populated with checkboxes in a wpf application.

enter image description here

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?


Solution

  • 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;
    }