无法为密钥绑定

时间:2016-01-29 00:10:45

标签: wpf .net-4.5

我有一个包含Dev Express网格控件的UserControl,我正在尝试连接一个命令,以便在用户按下删除键时选择一行。

我的第一次迭代是:

<dxg:GridControl.InputBindings>
    <KeyBinding Key="Delete" Command="{Binding DataContext.DeleteItemCommand}"/>
</dxg:GridControl.InputBindings>

在运行时使用Snoop检查结果时,我发现绑定有以下错误: System.Windows.Data Error:2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=DataContext.DeleteItemCommand; DataItem=null; target element is 'KeyBinding' (HashCode=39502614); target property is'Command' (type 'ICommand')

在做了一些研究后,我发现有几篇文章说他们能够通过添加相对来源来实现这一点,所以我改变了我的绑定:

<dxg:GridControl.InputBindings>
    <KeyBinding Key="Delete" Command="{Binding DataContext.DeleteItemCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=views:MyUserControl}}"/>
</dxg:GridControl.InputBindings>

现在在运行时我看到了这个错误: System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='MyProject.Views.MyUserControl', AncestorLevel='1''. BindingExpression:Path=DataContext.DeleteItemCommand; DataItem=null; target element is 'KeyBinding' (HashCode=35267081); target property is 'Command' (type 'ICommand')

在我做的研究中,我注意到这个功能是在.NET 4.0中添加的,但我使用的是.NET 4.5,因此不应该成为问题。

我还注意到所有示例都在窗口级别指定了InputBindings,所以在我的应用程序中做同样的事情我尝试将绑定移动到用户是不可行的控制水平,但收到相同的结果。

也不确定它是否重要但我的用户控件也继承了自定义基类,因此我不能尝试使用命名元素。

2 个答案:

答案 0 :(得分:2)

请尝试将代理用于包含DeleteItemCommand命令定义的DataContext,并使用该代理访问所需的命令。我认为您无法访问该命令并出现BindingExpression错误的原因是您与DataGrid对象不在同一逻辑树中。在我看来,有几点可以帮助你解决问题。

代理类:

public class FreezableProxyClass : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new FreezableProxyClass();
    }


    public static readonly DependencyProperty ProxiedDataContextProperty = DependencyProperty.Register(
        "ProxiedDataContext", typeof (object), typeof (FreezableProxyClass), new PropertyMetadata(default(object)));

    public object ProxiedDataContext
    {
        get { return (object) GetValue(ProxiedDataContextProperty); }
        set { SetValue(ProxiedDataContextProperty, value); }
    }
}

代理类xaml声明(这是具有您需要的DataContext的控件的名称):

 <UserControl.Resources>
        <dataGridSoHelpAttempt:FreezableProxyClass x:Key="ProxyElement" ProxiedDataContext="{Binding Source={x:Reference This}, Path=DataContext}"/>
    </UserControl.Resources>

代理类使用

 <dxg:GridControl.InputBindings>
            <KeyBinding Key="Delete" Command="{Binding Source={StaticResource ProxyElement}, 
                Path=ProxiedDataContext.DeleteItemCommand}"/>
        </dxg:GridControl.InputBindings>

<强>更新

<Window x:Class="DataGridSoHelpAttempt.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dataGridSoHelpAttempt="clr-namespace:DataGridSoHelpAttempt"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="MainWindow" Height="350" Width="525" x:Name="This">
<Window.DataContext>
    <dataGridSoHelpAttempt:MainViewModel/>
</Window.DataContext>
<Grid x:Name="MyGrid">
    <Grid.Resources>
        <dataGridSoHelpAttempt:FreezableProxyClass x:Key="ProxyElement" ProxiedDataContext="{Binding Source={x:Reference This}, Path=DataContext}"/>
    </Grid.Resources>
</Grid></Window>

如您所见是包含网格的窗口的名称。因此我不需要定义FreezableProxyClass的相对绑定,它直接访问主窗口DataContext。 如果您对代码有疑问,我将很乐意为您提供帮助。

问候。

答案 1 :(得分:1)

我知道这听起来不太可能,但对我来说有用的是从一个样式中引用inputBinding集合作为静态资源。我怀疑这个重要的部分是它是一个静态资源,不一定是我从一个风格中这样做。

My Style绑定到TreeViewItem,而不是网格:

file-path/[project_name]/Pods/GoogleSymbolUtilities/Libraries/

我的itemBindings资源与您的类似:

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="behaviors:InputBinder.InputBindings" Value="{StaticResource itemBindings}"/>
</Style>

当我使用动态资源时,或者当我将绑定集合直接分配给控件时,我收到了您提到的错误消息。

我使用的InputBindings附加属性如下所示:

    <InputBindingCollection x:Key="itemBindings" x:Shared="False">
        <KeyBinding Command="{Binding F2Command}" Key="F2"/>
    </InputBindingCollection>
相关问题