DataGridCell Binded value update upon row selection change

362 views Asked by At

My propblem is that DataGrid sends new value set by user with GUI only when the selected line is changed. When I modify value in form and press "Enter" to confirm input, everything works fine (because "Enter" moves selection to next line). But when I modify value in cell and press with mouse to any other cell in current row, new value is assigned to cell but not sent to binded object. In debugger I see that converter's ConvertBack method is called but Field.Value property setter is not! Field.Value property setter breakpoint fires only after row selection change. How can I force my Model object value change after cell edit finish, not row selection changed?

DataGrid's style:

<Style x:Key="ElementDataGridStyle" TargetType="DataGrid">
    <Setter Property="AutoGenerateColumns" Value="False"/>
    <Setter Property="HeadersVisibility" Value="Column"/>
    <Setter Property="SelectionUnit" Value="Cell"/>
    <Setter Property="CellStyle">
        <Setter.Value>
            <Style TargetType="DataGridCell">               
                <Style.Triggers>
                    <Trigger Property="IsReadOnly" Value="true">
                        <Setter Property="Background" Value="LightGray"/>
                    </Trigger>                  
                </Style.Triggers>
                <EventSetter Event="Loaded" Handler="ElementDataGridStyleCellStyle_Loaded"/>
            </Style>
        </Setter.Value>
    </Setter>   
</Style>

Code that binds DataGrid to my Model

private void SetDataGridContent(DataGrid grid, Core.Item.ItemCollection collection)
{
    grid.Columns.Clear();            
    if (collection != null)
    {                       
        for (int i = 0; i < collection.FieldProps.Count; i++)
        {
            Core.FieldProp prop = collection.FieldProps[i];
            if (prop.VisualName != null)
            {               
                MultiBinding multiBinding = new MultiBinding()
                {
                    Converter = new Visual.FieldValueConverter()
                };
                multiBinding.Bindings.Add(new Binding($"Fields[{i}]"));
                multiBinding.Bindings.Add(new Binding($"Fields[{i}].Value"));
                DataGridTextColumn column = new DataGridTextColumn
                {
                    Binding = multiBinding,
                    Header = prop.VisualName,
                    IsReadOnly = !prop.UIEditable,                            
                };              
                SetColumnFieldIndex(column, i);                             
                grid.Columns.Add(column);                        
            }                    
        }       
    }
    grid.ItemsSource = collection;            
}

Fields - is ObservableCollection successor

sealed class FieldCollection : ObservableCollection<Field>

Field class implements INotifyPropertyChanged interface

public class Field : INotifyPropertyChanged
{
    private string _value;

    public string Value
    {
        get => _value;
        set
        {
            if (_value != value)
            {
                Modify(value);
                NotifyPropertyChanged();
            }
        }
    }

    private void Modify(string value)
    {
        _value = value;
    }

    protected void NotifyPropertyChanged([CallerMemberName]string propertyName = null)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Value converter looks like this:

class FieldValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return values[1];
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        object[] result = new object[2];
        result[0] = Binding.DoNothing; //DependencyProperty.UnsetValue;
        result[1] = value;
        return result;
    }
}
0

There are 0 answers