【问题标题】:Binding to property in owning window's viewmodel within a DataTemplate in Window.Resources在 Window.Resources 中的 DataTemplate 中绑定到拥有窗口的视图模型中的属性
【发布时间】:2012-06-16 12:52:59
【问题描述】:

我的 Window 资源部分中有一个 DataTemplate,它创建一个带有 ContextMenu 的 TextBlock。我希望能够设置 ContextMenu 中的 MenuItem 在我的 Window 视图模型中是否可见。我尝试通过设置ElementName 来访问Window 的DataContext,也尝试设置RelativeSource,但是这两种方法都导致了绑定错误。我不确定我还能尝试什么。

我创建了一个小例子来展示我正在尝试做的事情:

XAML:

<Window x:Class="DataTemplateTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">


<Window.Resources>
    <ResourceDictionary>
        <DataTemplate x:Key="TestDataTemplate">
            <TextBlock Text="{Binding}">
                <TextBlock.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Test" Visibility="{Binding Path=DataContext.MenuItemVisible, ElementName=Root}"/>
                    </ContextMenu>
                </TextBlock.ContextMenu>
            </TextBlock>
        </DataTemplate>
    </ResourceDictionary>
</Window.Resources>

<ScrollViewer x:Name="Root">
    <ItemsControl ItemsSource="{Binding Path=Items}" ItemTemplate="{StaticResource TestDataTemplate}" />
</ScrollViewer>

后面的代码:

using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

namespace DataTemplateTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        protected readonly MainWindowViewModel vm;

        public MainWindow()
        {
            InitializeComponent();
            vm = new MainWindowViewModel();
            DataContext = vm;
        }
    }

    public class MainWindowViewModel : INotifyPropertyChanged
    {
        private Visibility menuItemVisible = Visibility.Hidden;
        public Visibility MenuItemVisible { get { return menuItemVisible; } set { menuItemVisible = value; NotifyPropertyChanged("MenuItemVisible"); } }

        public List<string> Items { get; set; }

        public MainWindowViewModel()
        {
            Items = new List<string>() { "Alpha", "Beta", "Gamma" };
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

我得到的错误是

System.Windows.Data 错误:4:找不到与引用“ElementName=Root”进行绑定的源。 BindingExpression:Path=DataContext.MenuItemVisible;数据项=空; 目标元素是'MenuItem'(名称='');目标属性是 “可见性”(类型“可见性”)

当我在绑定中设置 RelativeSource 而不是 ElementName 时:

RelativeSource={RelativeSource Mode=FindAncestor, 
                AncestorType={x:Type ScrollViewer}}

我收到以下错误:

System.Windows.Data 错误:4:找不到绑定源 参考'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ScrollViewer', 祖先级别='1''。 BindingExpression:Path=DataContext.MenuItemVisible;数据项=空; 目标元素是'MenuItem'(名称='');目标属性是 “可见性”(类型“可见性”)

【问题讨论】:

    标签: wpf datatemplate


    【解决方案1】:

    我找到了答案here

    所以我所要做的就是访问窗口的 DataContext 了:

    Source={x:Reference Name=Root}
    

    找到了here 解释为什么 ElementName 在这种情况下不起作用。具体来说:

    我们没有继承上下文链接的最简单的例子可能是跨越 > 随机属性元素:

    <Button>
      <Button.ContextMenu>
        <ContextMenu/>
      </Button.ContextMenu>
    </Button>
    

    ContextMenu 既不是 Button 的视觉或逻辑子代,也不是上面列出的继承上下文案例之一(ContextMenu 不是 Freezable)。

    【讨论】:

    • 非常感谢!只有您的解决方案对我有用.. 其他 RelativeSource-Stuff 根本不起作用!
    猜你喜欢
    • 2013-03-22
    • 1970-01-01
    • 2017-08-17
    • 2011-10-15
    • 2020-07-20
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    相关资源
    最近更新 更多