CodeDada
CodeDada

Reputation: 435

How to display data in WPF datagrid in MVVM

My xaml code

<Window x:Class="SampleWPFApp.View.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewmodel="clr-namespace:SampleWPFApp.ViewModel"
        Title="Window1" Height="500" Width="500">
    <Window.Resources>
        <viewmodel:FirstPageViewModel x:Key="fp"></viewmodel:FirstPageViewModel>
    </Window.Resources>
<Grid>
    <TextBox HorizontalAlignment="Left" Height="23" Margin="75,38,0,0" TextWrapping="Wrap" Text="{Binding FirstName, Source={StaticResource fp}}" VerticalAlignment="Top" Width="120"/>
    <TextBox HorizontalAlignment="Left" Height="23" Margin="75,79,0,0" TextWrapping="Wrap" Text="{Binding LastName, Source={StaticResource fp}}" VerticalAlignment="Top" Width="120"/>
    <Button Content="Add" HorizontalAlignment="Left" Margin="104,118,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.093,1.636" Command="{Binding acomm, Source={StaticResource fp}}" />
    <DataGrid HorizontalAlignment="Left" Name="mydatagrid" Margin="47,194,0,0" VerticalAlignment="Top" Height="178" Width="385" ItemsSource="{Binding Path=MyDataGrid,Mode=TwoWay,NotifyOnSourceUpdated=True,NotifyOnTargetUpdated=True}" DataContext="{DynamicResource fp} " Loaded="DataGrid_Loaded"/>
</Grid>

My property where grid is bound to in ViewModel,

private List<Employee> mysampleGrid;
public List<Employee> MySampleGrid
{
    get
    {
        return mysampleGrid;
    }
    set
    {
        mysampleGrid = value;
        OnPropertyChanged("MySampleGrid");
    }
}

Method called when button is clicked in ViewModel,

public void AddDataToDb()
{            

    e.FirstName = FirstName;
    e.LastName = LastName;
    context.Employees.Add(e);
    context.SaveChanges();
    this.MySampleGrid = null;

    //Setting List to value from database after inserting into db
    MySampleGrid = context.Employees.Where(x => x.FirstName != null).ToList();

}

But even after setting value of list(which is bound to datagrid) from database grid is not getting updated/refreshed in UI.please help. i have implemented INotifyPropertyChanged interface also.

Upvotes: 2

Views: 13637

Answers (2)

suulisin
suulisin

Reputation: 1434

you can do a couple of things to improve your code.

  1. First i will suggest you use ObservableCollection since it has Change tracking mechanism.
  2. Also set the DataContext of your grid to your viewmodel instead of individual control's datacontext to your viewmodel

putting everything together your code show now look like this:

     private ObservableCollection<Employee> mysampleGrid=new ObservableCollection<Employee>();

            public ObservableCollection<Employee> MysampleGrid
            {
                get { return mysampleGrid; }
                set { mysampleGrid= value; }            
            }

public void AddDataToDb()
    {            

        e.FirstName = FirstName;
        e.LastName = LastName;
        context.Employees.Add(e);
        context.SaveChanges();
        this.MySampleGrid = null;

        //Setting List to value from database after inserting into db
        var employees = context.Employees.Where(x => x.FirstName != null).ToList();
        foreach(var employee in employees)
        mysampleGrid.Add(employee);
    }

then finally in your view

<Window x:Class="SampleWPFApp.View.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewmodel="clr-namespace:SampleWPFApp.ViewModel"
        Title="Window1" Height="500" Width="500">
    <Window.Resources>
        <viewmodel:FirstPageViewModel x:Key="fp"></viewmodel:FirstPageViewModel>
    </Window.Resources>
<Grid DataContext="{StaticResource fp}">
            <TextBox HorizontalAlignment="Left" Height="23" Margin="75,38,0,0" TextWrapping="Wrap" Text="{Binding FirstName}" VerticalAlignment="Top" Width="120"/>
            <TextBox HorizontalAlignment="Left" Height="23" Margin="75,79,0,0" TextWrapping="Wrap" Text="{Binding LastName}" VerticalAlignment="Top" Width="120"/>
            <Button Content="Add" HorizontalAlignment="Left" Margin="104,118,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.093,1.636" Command="{Binding acomm}" />
            <DataGrid HorizontalAlignment="Left" Name="mydatagrid" Margin="47,194,0,0" VerticalAlignment="Top" Height="178" Width="385" ItemsSource="{Binding Path=MysampleGrid,Mode=TwoWay,NotifyOnSourceUpdated=True,NotifyOnTargetUpdated=True}"  Loaded="DataGrid_Loaded"/>

        </Grid>

Upvotes: 4

Charles Mager
Charles Mager

Reputation: 26213

If you look at your ItemsSource binding:

ItemsSource="{Binding Path=MyDataGrid,Mode=TwoWay,NotifyOnSourceUpdated=True,NotifyOnTargetUpdated=True}"

You'll notice that the property you're binding to doesn't exist. This should be MySampleGrid.

As an aside, most of the contents of the binding can be omitted, this should be all that is required:

ItemsSource="{Binding MySampleGrid}"

It would also make sense to set the DataContext of your Window, the child elements will inherit from this and the remaining DataContext attributes can be removed.

Upvotes: 2

Related Questions