Search code examples
wpfmvvmdatagridcell

WPF Datagrid Get Cell Value in MVVM architecture


How to get selected Cell value from Datagrid?

What information i have looked? Everything where title was "WPF get cell value MVVM".

What i did? 1 step:

    <Page x:Class="PDB.UsersView"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:PDB"
      xmlns:PDB ="clr-namespace:PDBapi;assembly=PDBapi"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="UsersView"
      >

    <Page.DataContext>
        <PDB:UsersViewModel/>
    </Page.DataContext>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <!--Page Header info content-->
        <Grid Grid.Row="0">
            <TextBlock Text="{Binding ElementName=myGrd, Path=CurrentCell.Column.DisplayIndex}"/>
        </Grid>
        <!--Datagrid content-->
        <DataGrid x:Name="myGrd" 
                  SelectionMode="Single"
                  SelectionUnit="Cell"
                  IsReadOnly="True"
                  Grid.Row="1" 
                  ItemsSource="{Binding Users}" 
                  AutoGenerateColumns="True"

                  CanUserAddRows="False">
            <DataGrid.InputBindings>
                <MouseBinding MouseAction="RightClick"
                  Command="{Binding CellClickCommand}"
                  CommandParameter="{Binding ElementName=myGrd, Path=CurrentCell}" />
            </DataGrid.InputBindings>

        </DataGrid>
    </Grid>
</Page>

VM:

        public  UsersViewModel()
        {
            UserList = new ObservableCollection<User>();

            GetUsers();

            Users = CollectionViewSource.GetDefaultView(UserList);

            CellClickCommand = new RelayParamCommand((data) => GetValue(data));
        }

        public void GetUsers()
        {
            User user = new User();

            // Users = await user.GetUsers();
            UserList.Add(new User
            {
                Name = "Marius",
                Departament = "some",
                Tabelis = 5
            });

            UserList.Add(
            new User
            {
                Name = "Darius",
                Departament = "unknown",
                Tabelis = 20
            });
        }

        private void GetValue(object data)
        {

            var some = (DataGridCellInfo)data;

            //Returns only number
            Console.WriteLine(some.Column?.DisplayIndex.ToString());
        }
    }

But with this approach i faced 2 issues: In xaml page i added textblock for testing which text was binded to datagrid currentCell. When i click right mouse button it shows int value correctly. But in my GetValue(object data) function console return null at first right click and from second time returns int value, but value in console is always diferent from textblock value, i have to click two times on same cell to get right cell position. That is completly wrong. How to solve that?

Another issue: How to get real value from currentCell i have binded?

What i did? 2 step:

In xaml i binded datagrid currentCell to VM property CurrentCell="{Binding Cell}" I got value it was ok, but still it returns only DataGridCellInfo object. I tried to cast to Users object and various things but i failed to get value of cell. Can someone provide good practice to get cell value from datagrid?


Solution

  • The data grid is bound to a collection of users, so each user is represented by one row, not one cell. That's why CurrentCell returns a DataGridCellInfo

    If you want the user, bind to CurrentItem instead.

    In XAML:

    <DataGrid 
        ItemsSource="{Binding Users}"
        CurrentItem="{Binding SelectedUser}"... 
    

    In the view model:

    private user selectedUser;
    public user SelectedUser
    {
        get => selectedUser;
        set
        {
            var u = value as user;
            selectedUser = u;
        }
     }