2016-01-29 70 views
0

我有一个包含Dev Express网格控件的用户控件,我试图连接一个命令以处理用户在选中某行时按下删除键的情况。无法为键绑定提供绑定

我的第一次迭代是:

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

当在运行时用史努比检查结果我看到这个错误的结合: 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

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

Proxy类:

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); } 
    } 
} 

Proxy类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。 如果您在代码方面遇到问题,我很乐意为您提供帮助。

问候。

+0

这不起作用,在打开的形式{X:参考本}绑定引发错误:'未解决的引用“This'' – Phaeze

+0

我可以通过将代理绑定到'{Binding RelativeSource = {RelativeSource AncestorType = {x:Type views:MyUserControl}}来获得代码的工作方式' – Phaeze

+0

@Peeze这是主窗口或控件的名称,你对此感兴趣。请参阅更新。 – Ilan

1

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

我的风格是绑定到树型视图,而不是一个网格:

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

我itemBindings资源看着你类似:

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

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

化InputBindings附加属性我用看起来如下:

public static class InputBinder 
{ 
    public static readonly DependencyProperty InputBindingsProperty = DependencyProperty.RegisterAttached 
    (
     "InputBindings", 
     typeof(InputBindingCollection), 
     typeof(InputBinder), 
     new FrameworkPropertyMetadata(new InputBindingCollection(), (sender, e) => 
     { 

      var element = (UIElement)sender; 
      if (element != null) 
      { 
       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); 
    } 
}