我的问题是,只有当选定的行被更改时,DataGrid才会使用GUI发送用户设置的新值。当我在表单中修改值并按"输入"为了确认输入,一切正常(因为"输入"将选择移到下一行)。但是当我修改单元格中的值并用鼠标按下当前行中的任何其他单元格时,新值将分配给单元格但不会发送到绑定对象。在调试器中,我看到转换器的ConvertBack方法被调用,但Field.Value属性设置器不是! Field.Value属性setter断点仅在行选择更改后触发。如何在单元格编辑完成后强制模型对象值更改,而不是更改行选择?
DataGrid的风格:
<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>
将DataGrid绑定到我的模型的代码
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;
}
字段 - 是ObservableCollection后继者
sealed class FieldCollection : ObservableCollection<Field>
Field类实现了INotifyPropertyChanged接口
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;
}
值转换器如下所示:
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;
}
}