Home > other >  What is the correct way to get the selected rows count using mvvm and c#?
What is the correct way to get the selected rows count using mvvm and c#?

Time:12-30

In my WPF app I have a datagrid like

<DataGrid
                SelectedItem="{Binding SelItm, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                ItemsSource="{Binding FilteredStudents}"
                SelectionMode="Extended"
                AutoGenerateColumns="False"
                IsReadOnly="True"
                SelectionUnit="FullRow"
                HeadersVisibility="Column"
                <DataGrid.Columns>
                    <DataGridTextColumn
                        Header="Bill No."
                        Binding="{Binding Path=Name, Mode=OneWay}"
                        Width="260"
                        IsReadOnly="True" />
                    <DataGridTextColumn
                        Header="Bill Date"
                        Binding="{Binding Path=Address, Mode=OneWay}"
                        Width="200"
                        IsReadOnly="True" />
                    <DataGridTextColumn
                        Header="Amount"
                        Binding="{Binding Path=Age, Mode=OneWay}"
                        Width="210"
                        IsReadOnly="True" />
                </DataGrid.Columns>
            </DataGrid>

The itemsource of the datagrid is an ICollectionView called FilteredStudents. I've created a property selrows in my viewmodel which I binded to a label to display the selected rows count using like selrows = SelItm.Count();.

    private ICollectionView _allFilteredStudents;
    public ICollectionView FilteredStudents
    {
        get
        {
            if(_allFilteredStudents == null)
            {
                this._allFilteredStudents = new ListCollectionView(GetAllStudents)
                {
                    Filter = o => ((Students)o).Name != "Ram"
                };
            }
            return _allFilteredStudents;
        }
    }

But it is displaying incorrect result.

BTW, my database looks like

enter image description here

What is the proper way to get the selected rows count of a WPF datagrid following mvvm pattern?

CodePudding user response:

Here is the solution:

If you are going to show the number of the selected row in the view, simply choose a name for the grid and bind to SelectedItems.Count of the grid.

In order to access selected items count in your c# code, you can add a IsSelected property to the StudentModel and bind it to the row's IsSelected attribute using RowStyle. This way whenever a row is selected/unselected, the IsSelected property of the StudentModel will be updated in the code and you can find selected students using that proertry like this FilteredStudents.Cast<StudentModel>().Count(i => i.IsSelected)

<Grid>
     <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Button Content="GetSelectedRowsCount" Command="{Binding ButtonCommand}"/>
    <TextBlock Grid.Row="1" Text="{Binding ElementName=grid, Path=SelectedItems.Count}"/>
    <DataGrid Grid.Row="2" x:Name="grid"
            ItemsSource="{Binding FilteredStudents}"
            SelectionMode="Extended"
            AutoGenerateColumns="False"
            IsReadOnly="True"
            SelectionUnit="FullRow"
            HeadersVisibility="Column" >
        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Setter Property="IsSelected" Value="{Binding Path = IsSelected}"/>
            </Style>
        </DataGrid.RowStyle>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Id" Binding="{Binding Path=Id, Mode=OneWay}"/>
            <DataGridTextColumn Header="Name" Binding="{Binding Path=Name, Mode=OneWay}"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

Now there is a IsSelected property in your StudentModel you can find how many rows are selected by filtering the collection in your code.

Here is the student model:

public class StudentModel : Notifier
{
    private int _id;
    public int Id
    {
        get { return _id; }
        set
        {
            this._id = value;
            RaisePropertyChanged();
        }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            this._name = value;
            RaisePropertyChanged();
        }
    }

    private bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            this._isSelected = value;
            RaisePropertyChanged();
        }
    }
}

and this is the viewModel:

public class AppPresenter : Notifier
{
    private ICollectionView _allFilteredStudents;
    public ICollectionView FilteredStudents
    {
        get
        {
            if (_allFilteredStudents == null)
            {
                this._allFilteredStudents = new ListCollectionView(GetAllStudents())
                {
                    Filter = o => ((StudentModel)o).Name != "Ram"
                };
            }
            return _allFilteredStudents;
        }
    }

    public List<StudentModel> GetAllStudents()
    {
        return new List<StudentModel>()
        {
            new StudentModel(){ Id=1, Name="name1"},
            new StudentModel(){ Id=2, Name="name2"},
            new StudentModel(){ Id=3, Name="name3"},
            new StudentModel(){ Id=4, Name="name4"},
        };
    }


public int GetSelectedRowCount()
{
    var selrows = FilteredStudents.Cast<StudentModel>().Count(i => i.IsSelected);

    return selrows;
}


private RelayCommand _buttonCommand;

public RelayCommand ButtonCommand
{
    get
    {
        if (_buttonCommand == null)
        {
            _buttonCommand = new RelayCommand(param => this.GetSelectedRowCount());
        }

        return _buttonCommand;
    }
}
     
}

Finally this is the MainWindow.cs

public MainWindow()
{
    InitializeComponent();

    this.DataContext = new AppPresenter();
}
  • Related