Search code examples
c#wpflistviewcheckboxlist

How to show that the checkbox is actually checked


I'm writing a program that allows a user to select multiple files and make things happen with them. I use checkboxes to select all needed files binded to a ListView. I need to have a button to select all files at once. The backend part works, frontend not.

I tried multithreading it, using a Refresh() method and researching everywhere for a problem like mine

this is how the Listview is populated with files and for each file there's a checkbox:

<ListView   Grid.Row="0" VerticalAlignment="Top" Height="400" BorderBrush="Black" BorderThickness="2" Grid.ColumnSpan="4"  ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" ItemsSource="{Binding Files}" Background="White">
                <ListView.View>
                    <GridView AllowsColumnReorder="False" >
                        <GridViewColumn DisplayMemberBinding="{Binding File.FullName}"  Header="Full Name" Width="200" />
                        <GridViewColumn DisplayMemberBinding="{Binding File.Name}" Header="Name" Width="200" />
                        <GridViewColumn DisplayMemberBinding="{Binding File.LastWriteTime, StringFormat='dd-MM-yyyy'}" Header="Last Modified" Width="200"/>
                        <GridViewColumn DisplayMemberBinding="{Binding File.Length}" Header="Size" Width="150"/>
                        <GridViewColumn Header="Select" Width="100" >
                            <GridViewColumn.CellTemplate >
                                <DataTemplate >
                                    <CheckBox x:Name="cb1" IsChecked="{Binding Path=Selected}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </ListView.View>

Note: the x:Name="cb1" is a test to check if I can use it from MainWindow.xaml.cs, but it doesn't work ( maybe because it has issues with multiple files?)

here is how the backend of the selectAll() method works:

private void SelectAll()
        { //1st version. this works but checkboxes are not flagged
            var dc = DataContext as FileList;
            foreach (var _file in dc.Files)
            {
                _file.Selected = true;

            }
            //2nd version. this doesn't work at all
            for (int i = 0; i < cb1.Items.Count; i++)
            {
                cb1.SetItemChecked(i, true); //cb1 doesn't exist in the current context
            }

        }

I have one class that is called FileWrapper, which is a FileInfo class to which I added a "Selected" bool property, which is binded to the "IsChecked" argument. The FileList is used to create a List of FileWrappers.

I, as the author of this code, know exactly that whenever the select all button is clicked, all the files are selected. Since I am not the enduser of the program, I need a graphical element to tell the user which files are selected and which not. It could also be that the user needs 100 of the 102 files in the list, so it would be quicker for him to first select all and then deselect 2 of them.


Solution

  • You can change your model as below to update the UI.

    public class FileWrapper : INotifyPropertyChanged
    {
        private FileInfo _file;
        private bool _selected; 
    
        public FileWrapper(FileInfo file) 
        { 
            File = file; 
            Selected = false; 
        } 
    
        public FileInfo File 
        { 
            get { return _file; }
            set
            {
                _file = value;
                OnPropertyChanged("File")
            }
        } 
    
        public bool Selected 
        { 
            get { return _selected ; }
            set
            {
                _selected = value;
                OnPropertyChanged("Selected")
            }
        } 
    
        public event PropertyChangedEventHandler PropertyChanged;  
        private void OnPropertyChanged(string propertyname) 
        {  
            if (PropertyChanged != null) 
            {  
                PropertyChanged(this, new PropertyChangedEventArgs(propertyname));  
            }  
        }  
    }
    

    Refer : https://www.c-sharpcorner.com/article/explain-inotifypropertychanged-in-wpf-mvvm/ for understanding INotifyPropertyChange interface