3
votes

I'm binding datas from a DbSet to a DataGrid thanks to an observable Collection. The way DbSet=>DataGrid works well, but the way DataGrid=>DbSet doesn't at all.

This is some codes to show you what I've done:

First of all, the Datagrid with the Binding properties:

<DataGrid x:Name="DonneesBrutes" ItemsSource="{Binding Path=.ResultatCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="10,65,0,0" AutoGenerateColumns="False" EnableRowVirtualization="True" RowDetailsVisibilityMode="VisibleWhenSelected">
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="PMRQ" Width="*" Binding="{Binding Path=.TOTMPMRQ, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="PMRQ"></DataGridTextColumn>
        <DataGridTextColumn x:Name="LibellePMRQ" Width="*" Binding="{Binding Path=.LibelléTOTApres, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Libellé PMRQ"></DataGridTextColumn>
        <DataGridTextColumn x:Name="Ligne" Width="*" Binding="{Binding Path=.Remarque, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Ligne"></DataGridTextColumn>
        <DataGridTextColumn x:Name="OTM" Width="*" Binding="{Binding Path=.TOTMPMRQ, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="OTM"></DataGridTextColumn>
        <DataGridTextColumn x:Name="TOTM" Width="*" Binding="{Binding Path=.SiModifie, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="TOTM"></DataGridTextColumn>
        <DataGridTextColumn x:Name="LibelleTOTM" Width="*" Binding="{Binding Path=.LibelléTOTApres, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Libellé OTM"></DataGridTextColumn>
        <DataGridTextColumn x:Name="GA" Width="*" Binding="{Binding Path=.Groupe_D_alerte, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="GA"></DataGridTextColumn>
        <DataGridTextColumn x:Name="Discipline" Width="*" Binding="{Binding Path=.NomTable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Discipline"></DataGridTextColumn>
        <DataGridTextColumn x:Name="DisciplineSubstituee" Width="120" Binding="{Binding Path=.NomChamp, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Discipline Substituée"></DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

This is the ResultatCollection which is the ObservableCollection I made to bind datas from DbSet to DataGrid:

class ViewModel:INotifyPropertyChanged
{
    private BDDInterneEntities _BDDInterneEntities;

    public ViewModel()
    {
        _BDDInterneEntities = new BDDInterneEntities();
        ResultatCollection = new ObservableCollection<Resultat>(_BDDInterneEntities.Resultat);
    }         
    public ObservableCollection<Resultat> ResultatCollection { get; set; }


    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string property)
    {
        if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }

    }
}

And then this is what the DbSet Resultat looks like:

public partial class Resultat:INotifyPropertyChanged
{
    public string NomTable { get; set; }
    public string Groupe_D_alerte { get; set; }
    public string NomChamp { get; set; }
    public string TOTMPMRQ { get; set; }
    public string SiModifie { get; set; }
    public string LibelléTOTAvant { get; set; }
    public string LibelléTOTApres { get; set; }
    public string Remarque { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }

    }
}

I have heard speaking about DataGrid.Items.refresh() but it sounds not working, DataGrid.ItemsSource = null then DataGrid.ItemsSource = myDataSource but it doesn't too.

I have heard too the mode=TwoWay and UpdateSourceTrigger=PropertyChanges were enough, I'm quite lost.

Thanks in advance for the help.

Greetings.

1
Is that your actual implementation of Resultat? If so then you only technically implemented INotifyPropertyChanged but ignored to actually raise the event if those properties change. (Same applies to ViewModel) - Dirk
Yes, it is the actual implementation of Resultat. You mean I have implemented the INotifyPropertyChanged, but I haven't defined what it is supposed to do, is that correct? - Kraenys

1 Answers

2
votes

In order to receive binding notifications you have to implement INotifyPropertyChanged correctly. The way you did it made it compilable, but not much else.

Every time a externally visible property changes you have to raise the PropertyChanged event. That's why you normally see code like

private int myProperty;

public int MyProperty
{
    get { return myProperty; }
    set
    {
        if (myProperty != value)
        {
            myProperty = value;
            OnPropertyChanged("MyProperty");
        }
    }
}

Of course you must not write directly to the field but use the property instead if you want to notify users of that class about property changes.


As you can see this gets quite tedious which is why several MVVM frameworks offer simplified versions, but you can also do your own version of it, for example

protected void Set<T>(ref T field, T newValue, string propertyName)
{
    if (field != newValue)
    {
        field = newValue;
        OnPropertyChanged(propertyName);
    }
}

Then your property would become

public int MyProperty
{
    get { return myProperty; }
    set { Set(ref myProperty, value, "MyProperty"); }
}