2016-01-29 73 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); 
    } 
}