Datacontext 在 DataGridTemplateColumn 中不可用
Datacontext not available in DataGridTemplateColumn
我有以下网格:
<DataGrid
x:Name="CandiesDataGrid"
ItemsSource="{Binding Candies}"
SelectedItem="{Binding SelectedCandy}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding CandySelectedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTextColumn KeyboardNavigation.IsTabStop="False" IsReadOnly="True" Width="100" Header="{l:LocText Candy_Prop1}" Binding="{Binding CandyInfo.Name}"/>
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="IsConfirmed" Grid.Column="0"
Style="{StaticResource CandyCheckBox}"
IsChecked="{Binding IsConfirmed, Mode=TwoWay}"
Margin="-75 0 0 0"
Command="{Binding IsConfirmedCommand}">
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
我的 属性 使用 OnPropertyChanged
。不但不改变IsConfirmed
的值,也不执行ICommand
IsConfirmedCommand
.
我在网上搜索了一下,好像DataGridTemplateColumn
丢了datagrid
的ItemSource
。
我确实尝试将 RelativeSource
放在复选框的 mode=TwoWay
之后,但它不起作用。
有什么方法可以访问我的 TemplateColumn 中的 ItemSource 吗?
编辑:
//Properties
public ObservableCollection<Candy> Candies{ get; } = new ObservableCollection<Candy>();
public Candy SelectedCandy { get { return _selectedCandy; } set { SetProperty(ref _selectedCandy, value); } } //SetProperty acts as OnPropertyChanged
private Candy _selectedCandy;
//Constructor:
public CandyClass()
{
IsConfirmedCommand = new DelegateCommand(IsConfirmedCommand_Execute);
}
//Method
private void IsConfirmedCommand_Execute()
{
//Doing something
}
在您的 CellTemplate 中,DataContext 是 DataGrid 行,无论它是什么(Candy
在这种情况下)。因此,默认情况下,Candy
实例将是该 DataTemplate 中任何绑定的 Source
属性。绑定将在此处查找路径中指定的 属性(在本例中为 IsConfirmed
和 IsConfirmedCommand
)。
这就是您想要的:您在网格中有不止一行,而该行通常是您在单元格中关心的内容。 That or the field:但通常情况下,一个单元格模板会想要查看多个字段,因此它们会为您提供整行。
但在这种情况下,您想返回并从父视图模型中获取一些东西。视图模型没有自然的 parent/child 层次结构,但如果您愿意,可以给它们一个:Candy 可以有一个 Parent
属性,它引用了拥有 Candies
集合的视图模型.如果你这样做了,你可以像这样绑定:
Command="{Binding Parent.IsConfirmed}"
但这不是常见的做法。我不知道这是否是一个特别好的主意。
我们不需要这样做的一个原因是我们可以告诉绑定使用不同的来源。 UI 元素 do 具有自然的 parent/child 层次结构,绑定可以导航它。如果你做对了,你的父视图模型将是某处某处的 DataContext。
{Binding Path=DataContext.IsConfirmed,
RelativeSource={RelativeSource AncestorType=DataGrid}}
"Walk the UI tree upwards until you find a DataGrid. That's your source. Now, once you have a source, find the source object's DataContext property, if any. If it's got a DataContext, take the value of DataContext and look on that object for some property called IsConfirmed."
DataGrid 有一个 DataContext 属性。由于您对 Candies
的绑定有效,我们知道 DataContext 必须是具有 Candies
属性 的 class。你向我保证 class 也有 IsConfirmed
。
因此:
<DataTemplate>
<CheckBox
Style="{StaticResource CandyCheckBox}"
IsChecked="{Binding DataContext.IsConfirmed,
RelativeSource={RelativeSource AncestorType=DataGrid}}"
Margin="-75 0 0 0"
Command="{Binding DataContext.IsConfirmedCommand,
RelativeSource={RelativeSource AncestorType=DataGrid}}"
/>
</DataTemplate>
我有以下网格:
<DataGrid
x:Name="CandiesDataGrid"
ItemsSource="{Binding Candies}"
SelectedItem="{Binding SelectedCandy}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding CandySelectedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTextColumn KeyboardNavigation.IsTabStop="False" IsReadOnly="True" Width="100" Header="{l:LocText Candy_Prop1}" Binding="{Binding CandyInfo.Name}"/>
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="IsConfirmed" Grid.Column="0"
Style="{StaticResource CandyCheckBox}"
IsChecked="{Binding IsConfirmed, Mode=TwoWay}"
Margin="-75 0 0 0"
Command="{Binding IsConfirmedCommand}">
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
我的 属性 使用 OnPropertyChanged
。不但不改变IsConfirmed
的值,也不执行ICommand
IsConfirmedCommand
.
我在网上搜索了一下,好像DataGridTemplateColumn
丢了datagrid
的ItemSource
。
我确实尝试将 RelativeSource
放在复选框的 mode=TwoWay
之后,但它不起作用。
有什么方法可以访问我的 TemplateColumn 中的 ItemSource 吗?
编辑:
//Properties
public ObservableCollection<Candy> Candies{ get; } = new ObservableCollection<Candy>();
public Candy SelectedCandy { get { return _selectedCandy; } set { SetProperty(ref _selectedCandy, value); } } //SetProperty acts as OnPropertyChanged
private Candy _selectedCandy;
//Constructor:
public CandyClass()
{
IsConfirmedCommand = new DelegateCommand(IsConfirmedCommand_Execute);
}
//Method
private void IsConfirmedCommand_Execute()
{
//Doing something
}
在您的 CellTemplate 中,DataContext 是 DataGrid 行,无论它是什么(Candy
在这种情况下)。因此,默认情况下,Candy
实例将是该 DataTemplate 中任何绑定的 Source
属性。绑定将在此处查找路径中指定的 属性(在本例中为 IsConfirmed
和 IsConfirmedCommand
)。
这就是您想要的:您在网格中有不止一行,而该行通常是您在单元格中关心的内容。 That or the field:但通常情况下,一个单元格模板会想要查看多个字段,因此它们会为您提供整行。
但在这种情况下,您想返回并从父视图模型中获取一些东西。视图模型没有自然的 parent/child 层次结构,但如果您愿意,可以给它们一个:Candy 可以有一个 Parent
属性,它引用了拥有 Candies
集合的视图模型.如果你这样做了,你可以像这样绑定:
Command="{Binding Parent.IsConfirmed}"
但这不是常见的做法。我不知道这是否是一个特别好的主意。
我们不需要这样做的一个原因是我们可以告诉绑定使用不同的来源。 UI 元素 do 具有自然的 parent/child 层次结构,绑定可以导航它。如果你做对了,你的父视图模型将是某处某处的 DataContext。
{Binding Path=DataContext.IsConfirmed,
RelativeSource={RelativeSource AncestorType=DataGrid}}
"Walk the UI tree upwards until you find a DataGrid. That's your source. Now, once you have a source, find the source object's DataContext property, if any. If it's got a DataContext, take the value of DataContext and look on that object for some property called IsConfirmed."
DataGrid 有一个 DataContext 属性。由于您对 Candies
的绑定有效,我们知道 DataContext 必须是具有 Candies
属性 的 class。你向我保证 class 也有 IsConfirmed
。
因此:
<DataTemplate>
<CheckBox
Style="{StaticResource CandyCheckBox}"
IsChecked="{Binding DataContext.IsConfirmed,
RelativeSource={RelativeSource AncestorType=DataGrid}}"
Margin="-75 0 0 0"
Command="{Binding DataContext.IsConfirmedCommand,
RelativeSource={RelativeSource AncestorType=DataGrid}}"
/>
</DataTemplate>