如何在DataGridTemplateColumn的CellTemplate中应用KeyBinding?

时间:2016-03-15 11:59:34

标签: wpf xaml key-bindings datagridtemplatecolumn celltemplate

我有点卷曲的问题,我找不到任何关于...的完整和明确的信息。

我的要求非常简单:我想将KeyBinding应用于DataGridTemplateColumn。这样做的目的是在为该列命中 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等)代码。

0 个答案:

没有答案