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的值,也不执行ICommandIsConfirmedCommand.

我在网上搜索了一下,好像DataGridTemplateColumn丢了datagridItemSource

我确实尝试将 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 属性。绑定将在此处查找路径中指定的 属性(在本例中为 IsConfirmedIsConfirmedCommand)。

这就是您想要的:您在网格中有不止一行,而该行通常是您在单元格中关心的内容。 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>