0

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?

Tamal Banerjee
  • 503
  • 3
  • 20
  • you may add a property like `IsSelected` to the student model and bind it to the selection status of the row. the whole idea can be this. – Hossein Narimani Rad Dec 29 '22 at 14:29
  • @HosseinNarimaniRad Are you talking about trigger property `IsSelected` ? Can you demonstrate ? – Tamal Banerjee Dec 29 '22 at 14:33
  • No. why not you give a name to the grid then bind to the grid `SelectedItems.Count` – Hossein Narimani Rad Dec 29 '22 at 14:50
  • Because I also want to use the count in methods inside my viewmodel. – Tamal Banerjee Dec 29 '22 at 14:51
  • Does this answer your question? [Select multiple items from a DataGrid in an MVVM WPF project](https://stackoverflow.com/questions/22868445/select-multiple-items-from-a-datagrid-in-an-mvvm-wpf-project) – Andy Dec 29 '22 at 14:54
  • Selecteditem only gives the one item and hence is only useful if you can only select a single one. The approach hossein mentioned could also work with a style targetting datagridrow setting isselected to a binding. You would then iterate your collection to count those qualifying. – Andy Dec 29 '22 at 14:59
  • @TamalBanerjee I posted the complete example for your – Hossein Narimani Rad Dec 29 '22 at 15:14

1 Answers1

0

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();
}
Hossein Narimani Rad
  • 31,361
  • 18
  • 86
  • 116