C#/WPF : Binding to an element outside of the visual/logical tree

标签 c# wpf xaml data-binding

我正在使用扩展 WPF 工具包中的 DropDownButton 控件。在其中,我托管了一个 ListBox,在更改所选元素时,它应该隐藏包含的 DropDownButton。

我最初结合 Microsoft 的交互框架这样做的方法是:

<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 进行绑定(bind),而是尝试查找 DropDownButton 类型的祖先,但这也不起作用;跟踪绑定(bind)显示它只解析了 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)

谢谢!

最佳答案

好吧,我遇到了同样的问题(尽管是在 Silverlight 中)。 通过引入一个引用 DropDownButton 并且可以很容易地从 DropDownContent 中绑定(bind)的资源对象来解决它:

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

关于C#/WPF : Binding to an element outside of the visual/logical tree,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31785228/

相关文章:

c# - 如何以编程方式绑定(bind)到静态属性?

c# - 在 DataTemplate 上找不到 TargetType 属性

c# - ReadStreamAsDT - Filehelpers 和 C# - 如何使用 filehelpers 动态读取 CSV?

c# - 我应该在多个上下文中使用 ViewModels/模型吗?

c# - DataGrid 文本框 DataTrigger 条件未按预期工作

c# - 无法将附加属性绑定(bind)到另一个依赖属性

c# - 在linq查询结果中使用foreach的问题

c# - NET Core Cors 抛出错误

c# - 如何在 WPF Web 浏览器中获得相当于 CTRL-A/CTRL-C 的功能

c# - 数据网格模板 [WPF]