Why is wpf UpdateSourceTrigger not binding explicitly?

1.3k views Asked by At

I have two-way binding between a DataGrid and an object. I want to only save changes made in the DataGrid to the object when the user clicks a save button. As a first step, I set UpdateSourceTrigger=Explicit. I would have expected no binding to occur when I set that property to explicit (since I have not called UpdateSource() yet), but contrary to my expectation, the changes are bound to the object when I close and restart the program.

Why are my changes still binding to my object's settings?

Here is my relevant DataGrid code from my xaml file:

<DataGrid x:Name="DataGrid1" IsReadOnly="False"
                 AutoGenerateColumns="False" CanUserAddRows="False" SelectionUnit="Cell"
                  ItemsSource="{Binding data}">
            <DataGrid.DataContext>
                <Binding Source="{StaticResource myData}" UpdateSourceTrigger="Explicit"/>
            </DataGrid.DataContext>

            <DataGrid.Columns>
                <DataGridTextColumn Header="Field" Binding="{Binding Path=name, Mode=TwoWay, 
                        UpdateSourceTrigger=Explicit}" Width="Auto"/>
                <DataGridTextColumn Header="Length of Field" Binding="{Binding Path=length, Mode=TwoWay, 
                        UpdateSourceTrigger=Explicit}" Width="Auto"/>
            </DataGrid.Columns>
</DataGrid>
1

There are 1 answers

1
Olaru Mircea On BEST ANSWER

Try with a DataGridTemplateColumn instead of that TextColumn:

<Window x:Class="DataGridUpdateSourceTriggerOneWay.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DataGridUpdateSourceTriggerOneWay"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <DataGrid x:Name="DataGrid1" 
              IsReadOnly="False"
              AutoGenerateColumns="False"
              CanUserAddRows="False"
              SelectionUnit="Cell"
              ItemsSource="{Binding data}">

        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Field">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding Path=Name, Mode=TwoWay, 
                    UpdateSourceTrigger=Explicit}" Width="Auto"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Length of Field">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding Path=Length, Mode=TwoWay, 
                    UpdateSourceTrigger=Explicit}" Width="Auto"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

Data class is here :

public class Data : INotifyPropertyChanged
{
    private string _Name;

    public string Name
    {
        get { return _Name; }
        set
        {
            _Name = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Name"));
        }
    }

    private int _Length;

    public int Length
    {
        get { return _Length; }
        set
        {
            _Length = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Length"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

And my test code:

public partial class MainWindow : Window
{
    public ObservableCollection<Data> data { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        data = new ObservableCollection<Data>();
        data.Add(new Data() { Name = "Data1", Length = 1 });
        data.Add(new Data() { Name = "Data2", Length = 2 });
        this.DataContext = this;
    }
}

It will get to the PropertyChanged events only at the beginning and after that, when modifying values from the GUI it won't trigger. So at the end, you will be able to save your modifications from code behind.