您应该DataTemplate
在 WPF 中将其视为工厂。因此,我认为您实际上并不需要 的新实例DataTemplate
,您只希望根据您的上下文以不同的方式应用它。
如果我正确理解您的问题,问题是DataContext
您的DataGrid
Cells 不正确:它是 Row ViewModel 而您希望它是 Cell ViewModel(这很有意义)。然而,这是 DataGrid 的基本行为,并且可能与每行中的 Cells 由未设置依赖属性的DataGridCellsPresenter(基本上是一个ItemsControl
)持有的事实有关(因此解释了 bad )。ItemsSource
DataContext
我遇到了这个问题并找到了两种方法来解决这个问题(但我只设法完成了一项工作)。
第一个是继承DataGridCellsPresenter并覆盖OnItemChanged
方法来手动设置 ItemsSource。
protected override void OnItemChanged(object oldItem, object newItem)
{
var rowViewModel = newItem as ViewModel;
if (rowViewModel != null)
{
ItemsSource = rowViewModel.Items;
}
else
{
ItemsSource = null;
}
}
在您的情况下, rowViewModel.Items 应该指向类似 data[x] 的东西。但是,我在使用此修复程序时遇到了一些麻烦,无法使其正常工作。
第二种解决方案是子类DataGridCell
化并在ColumnProperty
. 您还必须进行子类DataGridCellsPresenter
化以使其创建正确的单元格控件
public class MyDataGridCell : DataGridCell
{
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
if (e.Property == ColumnProperty)
{
var viewModel = DataContext as YourViewModelType;
if (viewModel != null)
{
var column = (e.NewValue as DataGridTemplateColumn);
if (column != null)
{
var cellViewModel = viewModel[column.DisplayIndex];
DataContext = cellViewModel;
}
}
}
base.OnPropertyChanged(e);
}
}
public class MyDataGridCellsPresenterControl : DataGridCellsPresenter
{
protected override System.Windows.DependencyObject GetContainerForItemOverride()
{
return new MyDataGridCell();
}
}
最后,您还必须覆盖 DataGridRow 默认 ControlTemplate 以使其使用您的自定义DataGridCellsPresenter
来代替原来的DataGridCellsPresenter
.
<ControlTemplate x:Key="DataGridRowControlTemplate" TargetType="{x:Type DataGridRow}">
<Border x:Name="DGR_Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<SelectiveScrollingGrid>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</SelectiveScrollingGrid.RowDefinitions>
<local:MyDataGridCellsPresenter Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" Visibility="{TemplateBinding DetailsVisibility}">
<SelectiveScrollingGrid.SelectiveScrollingOrientation>
<Binding Path="AreRowDetailsFrozen" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}">
<Binding.ConverterParameter>
<SelectiveScrollingOrientation>Vertical</SelectiveScrollingOrientation>
</Binding.ConverterParameter>
</Binding>
</SelectiveScrollingGrid.SelectiveScrollingOrientation>
</DataGridDetailsPresenter>
<DataGridRowHeader Grid.RowSpan="2" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical">
<DataGridRowHeader.Visibility>
<Binding Path="HeadersVisibility" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}">
<Binding.ConverterParameter>
<DataGridHeadersVisibility>Row</DataGridHeadersVisibility>
</Binding.ConverterParameter>
</Binding>
</DataGridRowHeader.Visibility>
</DataGridRowHeader>
</SelectiveScrollingGrid>
</Border>
</ControlTemplate>