2015-08-03 49 views
2

我使用扩展WPF工具包中的DropDownButton控件。在里面,我主持一个ListBox,当改变选定的元素时,应该隐藏包含DropDownButton。C#/ WPF:绑定到视觉/逻辑树之外的元素

我在与微软的互动框架一起这样做最初的做法是:

<xctk:DropDownButton x:Name="WorkspaceSelectorContainer" Content="This is the active workspace"> 
        <xctk:DropDownButton.DropDownContent> 
          <ListBox ItemsSource="{Binding workspaces}"> 
           <i:Interaction.Triggers> 
            <i:EventTrigger EventName="SelectionChanged"> 
             <ie:ChangePropertyAction PropertyName="IsOpen" Value="False" TargetObject="{Binding ElementName=WorkspaceSelectorContainer}"/> 
            </i:EventTrigger> 
           </i:Interaction.Triggers> 
          </ListBox> 
         </StackPanel> 
        </xctk:DropDownButton.DropDownContent> 
       </xctk:DropDownButton> 

但由于WorkspaceSelectorContainer没有发现这个没有工作。 而不是通过ElementName绑定,我试图找到类型DropDownButton的祖先,但这也没有工作;追踪绑定显示它只解析祖先到DropDownButton.DropDownContent的最外层元素,但没有更进一步;例如DropDownButton本身不是祖先树的一部分。

好了,我的下一个方法是

<ie:ChangePropertyAction PropertyName="IsOpen" Value="False" TargetObject="{Binding Source={x:Reference WorkspaceSelectorContainer}}"/> 

,但没有工作,要么因为它抛出一个异常

A first chance exception of type 'System.Xaml.XamlObjectWriterException' occurred in System.Xaml.dll 

Additional information: Cannot call MarkupExtension.ProvideValue because of a cyclical dependency. Properties inside a MarkupExtension cannot reference objects that reference the result of the MarkupExtension. 

不知道什么尝试了。有没有人有一个想法如何解决这个问题?

是否有可能以某种方式引用我的根网格包含一切,并从那里搜索DropDownButton元素? {Binding Source = {x:Reference MyRootGrid},ElementName = WorkspaceSelectorContainer}(这不起作用,因为我无法组合源和ElementName)

谢谢!

+0

您的标记有zombi标记。 – Martin

回答

3

那么我有同样的问题(尽管在Silverlight中)。 通过引入具有对DropDownButton的引用的资源对象解决了它,并可以很容易地从DropDownContent内势必:

<Foo.Resources> 
    <BindableObjectReference 
     x:Key="WorkspaceSelectorContainerReference" 
     Object="{Binding ElementName=WorkspaceSelectorContainer}"/> 
</Foo.Resources> 
<DropDownButton x:Name="WorkspaceSelectorContainer" ...> 
    <DropDownButton.DropDownContent> 
     ... 
     <ChangePropertyAction 
      PropertyName="IsOpen" 
      Value="False" 
      TargetObject="{Binding Path=Object, 
       Source={StaticResource WorkspaceSelectorContainerReference}}"/> 
     ... 
    </DropDownButton.DropDownContent> 
</DropDownButton> 

...和魔术对象

public class BindableObjectReference : DependencyObject 
{ 
    public object Object 
    { 
     get { return GetValue(ObjectProperty); } 
     set { SetValue(ObjectProperty, value); } 
    } 

    public static readonly DependencyProperty ObjectProperty = 
     DependencyProperty.Register("Object", typeof(object), 
     typeof(BindableObjectReference), new PropertyMetadata(null)); 
} 
+0

这样一个优雅的方式,终于谢谢这么多先生! – AgentFire

0
<ie:ChangePropertyAction PropertyName="IsOpen" Value="False" 
         TargetName="WorkspaceSelectorContainer" /> 
+0

不幸的是,这也行不通。虽然我不知道如何可能调试这一个,但我想这个问题可能与尝试使用ElementName = ...绑定TargetObject时相同...... – Bogey

+0

hmm,尝试将ListBox添加到与DropDownButton相同的NameScope - 例如在ListBox.Initialized事件中。只是从内存:'NameScope.SetNameScope(MyListBox,NameScope.GetNameScope(WorkspaceSelectorContainer);' – Liero