在样式中定义输入绑定

24
我正在使用MVVM设计模式创建WPF应用程序,并尝试扩展TabItem控件,以便在用户单击鼠标中键时关闭该选项卡。我尝试使用InputBindings来实现这一目标,在定义样式时它也很有效,但只适用于第一个选项卡。我已经学到,除非使用DependencyProperty将其附加,否则无法将InputBindings添加到样式中。因此,我遵循了这篇类似的文章(在此处...)并且它几乎奏效了。我可以使用中间鼠标按钮关闭一个选项卡,但是在其他选项卡上不起作用(所有选项卡都是在运行时添加并继承相同的样式)。

所以我需要一些帮助。为什么这只有第一次运行时有效,之后就失效了?显然,我可以创建一个自定义控件,继承自TabItem并使其正常工作,但我希望弄清楚这一问题,因为我可以看到它在我的项目中得到扩展。我不是DependencyProperties的专家,请帮帮我。谢谢!

样式:

<Style TargetType="{x:Type TabItem}">
    <Setter Property="w:Attach.InputBindings">
        <Setter.Value>
            <InputBindingCollection>
                <MouseBinding MouseAction="MiddleClick" 
                              Command="{Binding CloseCommand}"/>
            </InputBindingCollection>
        </Setter.Value>
    </Setter>
    ...
</Style>

public class Attach
{
    public static readonly DependencyProperty InputBindingsProperty =
        DependencyProperty.RegisterAttached("InputBindings", typeof(InputBindingCollection), typeof(Attach),
        new FrameworkPropertyMetadata(new InputBindingCollection(),
        (sender, e) =>
        {
            var element = sender as UIElement;
            if (element == null) return;
            element.InputBindings.Clear();
            element.InputBindings.AddRange((InputBindingCollection)e.NewValue);
        }));

    public static InputBindingCollection GetInputBindings(UIElement element)
    {
        return (InputBindingCollection)element.GetValue(InputBindingsProperty);
    }

    public static void SetInputBindings(UIElement element, InputBindingCollection inputBindings)
    {
        element.SetValue(InputBindingsProperty, inputBindings);
    }
}

1
我遇到了上述描述的确切问题,即使使用Daniel建议的代码也是如此。似乎在使用上面的Attach类时有些非常奇怪的事情发生,特别是在样式中。我发现当添加InputBindings时,DataContext有时会为空,因此当绑定发生时,它无法找到命令。我从未找到解决方案,但最终我按下面的答案复制了绑定。 - Asheh
2个回答

19

你的 "Attach" 类对我来说运行得很好!如果有人需要,诀窍是使用此样式,并带有 x:Shared 修饰符:

<InputBindingCollection x:Key="inputCollection" x:Shared="False">
        <KeyBinding Key="Del" Command="{Binding DeleteItemCommand}"/>
</InputBindingCollection>

<Style TargetType="{x:Type TabItem}">
    <Setter Property="w:Attach.InputBindings" Value="{StaticResource inputCollection}" />
    ...
</Style>

谢谢!


17

没关系,我自己想通了。最终我甚至没有使用上面的Attach类...而是在TabItem的ControlTemplate上使用了InputBindings(它是一个Border),所以看起来像这样...我不知道为什么我一开始没想到这个..:)

<ControlTemplate TargetType="{x:Type TabItem}">
    <Grid SnapsToDevicePixels="true">
        <Border x:Name="Bd" ...>
            <DockPanel>
                ...
            </DockPanel>
            <Border.InputBindings>
                <MouseBinding MouseAction="MiddleClick"
                              Command="{Binding CloseCommand}"/>
            </Border.InputBindings>
        </Border>
    </Grid>
    ...
</ControlTemplate>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接