0
votes

OK, so I have a WPF application using the MVVM pattern.

I have a DataGrid, ItemsSource is bound to an ObservableCollection and SelectedItem bound to a property of my Model, called CurrentCategory

 <DataGrid x:Name="LstCategories" Grid.Column="0" Grid.Row="1"  AutoGenerateColumns="false"  IsReadOnly="True"
              ItemsSource="{Binding Path=ReceivedCategories, Mode=TwoWay}" 
              HorizontalScrollBarVisibility="Disabled" GridLinesVisibility="None"
              CanUserAddRows="False" CanUserDeleteRows="False" CanUserSortColumns="True" Background="White"
              SelectedIndex="{Binding Path=SelectedIndex}" 
                      SelectedItem="{Binding CurrentCategory, UpdateSourceTrigger=PropertyChanged}">
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding Path=Description}" IsReadOnly="True" Header="Description" Width="300" />
                </DataGrid.Columns>
            </DataGrid>

A TextBox Text is bound to the Description property of CurrentCategory.

<TextBox x:Name="TbDescription" Grid.Row="0" Grid.Column="1" Width="250" Height="Auto" 

                     VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0"
                     Text="{Binding Path=CurrentCategory.Description, Mode=TwoWay}" />

And finally a Button that will be used to update the description to the database.

  <Button   Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Margin="10,0,0,0" 
                      Height="20" Width="120" Content="Update Description" 
                      Command="{Binding UpdateCategoryCommand}"
                      CommandParameter="{Binding Path=CurrentCategory.CategoryId}" />

This all works pretty much as expected.

However, I don't want the DataGrid record to automatically be edited as I change the text in the TextBox.

So it's logical to set the binding to One-Way. But then when I click the update button, the Description property is still the old value.

I have tried various modes for the data binding, and cannot get the exact behaviour I want.

Seems like a catch 22 situation.

Any ideas as to get the behaviour I am after?

Edit 1 - Working Solution

As mentioned by Amine, I added an extra property and bound the TextBox to it. I also had to add a check that value wasn't null in CurrentCategory. Probably because of the binding to the SelectedItem and ItemsSource and when the DataGrid is repopulated it binds to nothing making it null. My theory anyway.

And finally changed the method that checks if the update button should be enabled or not, and the method that updates to the database to use the EditedCategory property.

Working Code:

    private CategoryModel _currentCategory;
    public CategoryModel CurrentCategory
    {
        get { return _currentCategory; }
        set
        {
            if (value != null)
            {
                _currentCategory = value;

                EditedCategory = new CategoryModel
                {
                    CategoryId = value.CategoryId,
                    Description = value.Description
                };

                OnPropertyChanged("CurrentCategory");
            }
        }        
    }

    private CategoryModel _editedCategory;

    public CategoryModel EditedCategory
    {
        get { return _editedCategory; }
        set
        {
            _editedCategory = value;
            OnPropertyChanged("EditedCategory");
        }
    }


    /// <summary>
    /// Checks whether the Update button should be enabled or disabled
    /// </summary>
    /// <returns>True or False</returns>
    public bool CanUpdateCategory()
    {
        return !String.IsNullOrWhiteSpace(EditedCategory.Description);
    }

    /// <summary>
    /// Method to update the selected category
    /// </summary>
    /// <param name="id"></param>
    public void UpdateCategory(int id)
    {
        if (CurrentCategory.UpdateCategory(id, EditedCategory.Description))
            GetCategories();
    }
1
I think you need to use UpdateSourceTrigger=Explicit and notify your property on refresh button click or update button click.Abin
I tried that, still couldn't get the exact behaviour I wanted, or perhaps I wasn't using it correctly.Neill

1 Answers

1
votes

You need another property ex:"EditedCategory". When you select an item in DataGrid, you must create a new instance for EditedCategory.

private object currentCategory;
public object CurrentCategory
{
    get { return currentCategory; }
    set
    {
        currentCategory = value;
        EditedCategory = new object{ id = value.id....}
        this.OnPropertyChanged("CurrentCategory"); 

    }
}

private object editedCategory;
public object EditedCategory
{
    get { return editedCategory; }
    set
    {
        editedCategory = value;
        this.OnPropertyChanged("EditedCategory");

    }
}

And you bind TexBox to EditedCategory.