如何使用资源中的ElementName绑定?

时间:2014-12-02 08:37:36

标签: c# windows-runtime winrt-xaml

我已将ItemsFlyout添加到ItemsControl.ItemTemplate中的按钮。此外,我能够将当前项绑定为CommandParameter。 现在我想将Command绑定到MenuFlyoutItem。 在codebehind中:

LayoutRoot.DataContext = this;

因此,如果我绑定到LayoutRoot,我将实际绑定到我当前的UserControl。但以下绑定无效:

Command="{Binding ActivateProfileCommand, ElementName=LayoutRoot}"

它给出了输出中的错误,但它不起作用。 以下是完整的示例:

<controls:HeaderDecorator x:Uid="AccountsHeader" Text="Accounts" x:Name="LayoutRoot" Name="LayoutRoot">
    <controls:HeaderDecorator.Resources>
        <MenuFlyout x:Key="AccountMenuFlyout">
            <MenuFlyoutItem Text="Activate" Name="Activate" 
                        Command="{Binding ActivateProfileCommand, ElementName=LayoutRoot}"
                        CommandParameter="{Binding}" />
        </MenuFlyout>
    </controls:HeaderDecorator.Resources>
    <StackPanel Orientation="Vertical">
        <ItemsControl ItemsSource="{Binding Settings.Profiles}" >
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <HyperlinkButton Content="{Binding}"  FlyoutBase.AttachedFlyout="{StaticResource AccountMenuFlyout}" >
                        <i:Interaction.Behaviors>
                            <ic:ShowFlyoutBehavior />
                        </i:Interaction.Behaviors>
                    </HyperlinkButton>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</controls:HeaderDecorator>

似乎问题是我试图在参考资料中使用共享对象。我可以做吗?为什么不呢?

2 个答案:

答案 0 :(得分:2)

您在这里看到的问题是 MenuFlyoutItem 不再位于您认为的 datacontext 中。我会尽力解释这个问题,因为我知道谁和xaml一起工作的人已经遇到过这种情况,并且已经在墙上砸了好几天了。它也被称为在您的特定场景中不显示错误;进一步增加了混乱。

简而言之。当 MenuFmpout 添加到集合中每个项目的 ItemTemplate 中时,它可能无法访问您可能认为的 datacontext 。在这种情况下,控件现在所在的 datacontext 实际上是它所在的集合中的单个项目。

但是有一个解决方案。我有类似于你自己的东西。 ItemsControl 定义了 ItemsTemplate ,其中包含 UIElement FlyoutBase AP引用资源字典中定义的 MenuFlyout

除了我在绑定中不需要 ElementName 之外,xaml几乎相同。

但是,我现在已将注意力转移到该集合所持有的类型。我的代码看起来像这样。

public class AnItemToList
{
   public AnItemToList(Action commandDel)
   {
        TestCommand = new RelayCommand(commandDel);
   }
   public string Name { get; set; }
   public RelayCommand TestCommand { get; set; }
}

请注意,该命令正在项目本身中定义,并且我将通过构造函数传递命令将执行的方法。

MenuFlyoutItem 上的命令绑定所需做的就是

<MenuFlyoutItem Text="Activate"
                Name="Activate"
                Command="{Binding TestCommand}"/>

我没有在这里设置命令参数,因为我只是快速组建了一个基本模板Windows Phone应用程序,并且预先打包的ICommand实现没有设置委托来接受参数。

如果您现在在命令调用的方法中粘贴了一个断点,您将看到它将从绑定到该命令的任何 MenuFlyoutItem 中调用。引用它。

请记住,这不是解决这个问题的唯一方法;但这是我偶尔使用的一个。例如,在WPF XAML中,您可以使用 RelativeSource 在父控件的 datacontext 上查找命令。

希望这有帮助。

答案 1 :(得分:0)

这是一个通用的“配对”对象:

public class Pair : DependencyObject
{
    public static readonly DependencyProperty FirstProperty = DependencyProperty.Register("First",
        typeof(object), typeof(Pair), new PropertyMetadata(null));

    public static readonly DependencyProperty SecondProperty = DependencyProperty.Register("Second",
        typeof(object), typeof(Pair), new PropertyMetadata(null));

    public object First
    {
        get { return GetValue(FirstProperty); }
        set { SetValue(FirstProperty, value); }
    }

    public object Second
    {
        get { return GetValue(SecondProperty); }
        set { SetValue(SecondProperty, value); }
    }
}

在ItemTemplate中我放了这样的东西:

                <DataTemplate>
                    <Grid>
                        <Grid.Resources>
                            <viewModel:Pair x:Key="Tuple" First="{Binding DataContext, ElementName=LayoutRoot}" 
                                                           Second="{Binding}" />
                        </Grid.Resources>
                        <HyperlinkButton Content="{Binding Second.ProfileName}" 
                                     DataContext="{StaticResource Tuple}"
                                     FlyoutBase.AttachedFlyout="{StaticResource AccountMenuFlyout}" 
                        </HyperlinkButton>
                    </Grid>
                </DataTemplate>

现在我可以轻松地从我的资源中引用元组元素:

            <MenuFlyoutItem Text="Activate" Name="Activate" 
                        Command="{Binding First.ActivateProfileCommand}"
                        CommandParameter="{Binding Second}" />