1

我有一个卷曲的问题,我找不到任何完整和明确的信息......

我的要求很简单:我想将 KeyBinding 应用于 DataGridTemplateColumn。这样做的目的是在Delete按下该列的键时执行命令 - 如果Delete在网格上的其他任何位置按下键,则会执行不同的命令。两个 Delete 命令都存在于网格的 VM 中。

虽然我可以在网格级别定义一个键绑定,然后在命令中测试活动单元格属于哪个列,但这是一个混乱的解决方案,因为:

  • 在多个不同页面上使用网格时无法很好地扩展

  • 有问题的列被定义为 ResourceDictionary 中的资源

此外,我没有看到任何迹象表明这是不可能的……但它却让我无法理解。

我相信我的问题是因为当该单元格成为网格的当前单元格时,焦点不会自动应用于 CellTemplate。单元格上有一个焦点矩形,但单元格内没有触发焦点事件(我已经检查过了)。虽然像 TextBlocks 这样的只读控件可以接收焦点,但如果没有,则无法触发键绑定。键绑定的命令已正确绑定,因此绑定不是问题。

网格定义如下:

<DataGrid   x:Name="MyGrid"
            ItemsSource="{Binding Path=FilteredSortedData}"             
            >

    <DataGrid.Columns>
        <StaticResource ResourceKey="StatusColumn" />
        <StaticResource ResourceKey="MySpecialDeleteColumn" />
        <StaticResource ResourceKey="...etc..." />
    </DataGrid.Columns>
</DataGrid>

然后是专栏:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    x:Class="MyNamespace.GridColumns"
                    >
    <FrameworkElement x:Key="GridColProxy" Name="GridColProxy" DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True, Mode=OneWay}" />

    <DataGridTemplateColumn x:Key="MySpecialDeleteColumn"
                            x:Shared="False"
                            Header="My Special Delete Column"   
                            IsReadOnly="False"
                            >
        <DataGridTemplateColumn.CellTemplate>             
            <DataTemplate>
                <StackPanel >
                    <!-- keybinding doesn't work at this level  -->
                    <StackPanel.Style >
                        <Style TargetType="StackPanel">
                            <Setter Property="localBehaviours:InputBindingsBehaviour.AttachedKeyBindings">
                                <Setter.Value>
                                    <localBehaviours:KeyBindingObservable  >
                                        <KeyBinding Key="Delete" Command="{Binding Path=DataContext.DeleteItemsCommand, Source={StaticResource GridColProxy}, Mode=OneWay, NotifyOnTargetUpdated=True}" />
                                    </localBehaviours:KeyBindingObservable>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </StackPanel.Style>

                    <Grid >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>

                        <TextBlock  Grid.Column="0"
                                    Text="{Binding SomeProperty}"
                                    >
                            <TextBlock.Style>
                                <Style TargetType="TextBlock" >
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=MySpecialFlag, FallbackValue=false}" Value="True">
                                            <Setter Property="localBehaviours:InputBindingsBehaviour.AttachedKeyBindings">
                                                <Setter.Value>
                                                    <localBehaviours:KeyBindingObservable  >
                                                        <KeyBinding Key="Delete" Command="{Binding Path=DataContext.DeleteItemsCommand, Source={StaticResource GridColProxy}, Mode=OneWay, NotifyOnTargetUpdated=True}" />
                                                    </localBehaviours:KeyBindingObservable>
                                                </Setter.Value>
                                            </Setter>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </TextBlock.Style>
                        </TextBlock>
                        <Image  Source="{Binding ...}"
                                Grid.Column="1"
                                />
                    </Grid>
                </StackPanel>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>   

        <DataGridTemplateColumn.CellStyle>
            <Style TargetType="{x:Type DataGridCell}" >
                <Style.Triggers>
                    <!-- placing the keybinding here to apply to the grid cell doesn't have any effect... -->
                    <DataTrigger Binding="{Binding Path=MySpecialFlag, FallbackValue=false}" Value="True">
                        <Setter Property="localBehaviours:InputBindingsBehaviour.AttachedKeyBindings">
                            <Setter.Value>
                                <localBehaviours:KeyBindingObservable  >
                                    <KeyBinding Key="Delete" Command="{Binding Path=DataContext.DeleteItemsCommand, Source={StaticResource GridColProxy}, Mode=OneWay, NotifyOnTargetUpdated=True}" />
                                </localBehaviours:KeyBindingObservable>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGridTemplateColumn.CellStyle>
    </DataGridTemplateColumn>
</ResourceDictionary>  

笔记:

  • 忽略localBehaviours:KeyBindingObservable,它只是一个附加属性,用于在将键绑定分配给InputBindings附加控件的属性之前帮助拦截和检查键绑定。这很好用,这里没有问题。

  • 我已经展示了我尝试过键绑定的每个地方,它们都没有工作(被触发)。DataTrigger 绑定可以正常工作,因此请忽略它们。

  • 为简洁起见,省略了 CellEditingTemplate

所以我的问题是:

  • 如何强制 CellTemplate 项目接收(键盘)焦点,最好使用 XAML?或者有没有办法在单元格级别应用键绑定,以便无论显示的模板如何都能正常工作?

如果 XAML 解决方案不可行,则可以使用 ResourceDictionary 后面代码中的少量事件触发(PreviewKeyDown 等)代码。

4

0 回答 0