Я создал класс, полученный из DataGrid
, чтобы я мог переопределить шаблоны, используемые для типов столбцов, когда DataGrid.AutoGenerateColumn
установлен в True
. Вот мой DataGrid класс:Значение привязки WPF не обновляется до модели
public class DataGridEx : DataGrid
{
protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
{
base.OnAutoGeneratingColumn(e);
Type colDataType = e.PropertyType;
if (colDataType == typeof(DateTime))
{
// Create a new template column.
var templateColumn = new DataGridTemplateColumnEx();
templateColumn.Header = e.Column.Header;
templateColumn.CellTemplate = (DataTemplate)Resources["DateTimePickerCellTemplate"];
templateColumn.CellEditingTemplate = (DataTemplate)Resources["DateTimePickerCellEditingTemplate"];
templateColumn.SortMemberPath = e.Column.SortMemberPath;
templateColumn.ColumnName = e.PropertyName;
// Replace the auto-generated column with new template column
e.Column = templateColumn;
}
}
}
Однако это вызвало DataContext
нового DataGridTemplateColumn
быть связан с элементом строки, так что я должен был получить еще один класс из DataGridTemplateColumn
и переопределить GenerateElement()
и GenerateEditingElement()
функции, чтобы иметь возможность связываться содержимое шаблона возвращается к целевому свойству столбца элемента строки.
public class DataGridTemplateColumnEx : DataGridTemplateColumn
{
public string ColumnName { get; set; }
protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
// The DataGridTemplateColumn uses ContentPresenter with your DataTemplate.
var cp = (ContentPresenter)base.GenerateElement(cell, dataItem);
// Reset the Binding to the specific column. The default binding is to the DataRowView.
BindingOperations.SetBinding(cp, ContentPresenter.ContentProperty, new Binding(this.ColumnName));
return cp;
}
protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
// The DataGridTemplateColumn uses ContentPresenter with your DataTemplate.
var cp = (ContentPresenter)base.GenerateEditingElement(cell, dataItem);
// Reset the Binding to the specific column. The default binding is to the DataRowView.
BindingOperations.SetBinding(cp, ContentPresenter.ContentProperty, new Binding(this.ColumnName));
return cp;
}
}
А вот контроль, как представляется, на мой взгляд:
<c:DataGridEx AutoGenerateColumns="True" ItemsSource="{Binding}">
<c:DataGridEx.Resources>
<DataTemplate x:Key="DateTimePickerCellTemplate">
<TextBlock Text="{Binding}"/>
</DataTemplate>
<DataTemplate x:Key="DateTimePickerCellEditingTemplate">
<!-- Needed to specify Path=. or else got error about two-way binding requiring a path or xpath. -->
<DatePicker Text="{Binding Path=., Mode=TwoWay}"/>
</DataTemplate>
</c:DataGridEx.Resources>
</c:DataGridEx>
Это похоже на работу, насколько TextBlock
отображает значение свойства на элементе строки правильно. Но с CellEditingTemplate
элемент управления DatePicker
появляется, когда я пытаюсь отредактировать ячейку и имеет правильное начальное значение, но когда я меняю дату, изменения не сохраняются, значение источника НЕ обновляется.
Почему источник не обновляется здесь?
Я реализовал ваше решение, но двухсторонняя привязка не работает до сих пор, и я получаю эту ошибку в области вывода: 'System.Windows.Data Ошибка: Ошибка BindingExpression путь:: 40 свойство«Value» не найдено в 'object' '' DateTime '(HashCode = -1144325517)'. BindingExpression: Path = Value; DataItem = 'DateTime' (HashCode = -1144325517); целевым элементом является «TextBlock» (Name = ''); target свойство is 'Text' (type 'String') ' –
Я не думаю, что вы внесли изменения в GenerateEditingElement. Он по-прежнему привязывается к DateTime, а не к ObjectProxy. –
Извините, что вы правы. Я изменил переопределение «GenerateEditingElement», но не переопределение «GenerateElement» (для TextBlock). Теперь ошибка исчезла, но когда я изменяю значение в 'DatePicker', источник все еще не обновляется? –