3

Window の Resources セクション内に、ContextMenu で TextBlock を作成する DataTemplate があります。ContextMenu 内の MenuItem が Window のビュー モデル内から見えるかどうかを設定できるようにしたいと考えています。を設定して Window の DataContext にアクセスしようとしましたがElementName、 も設定しようとし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; DataItem=null; ターゲット要素は 'MenuItem' (Name='') です。ターゲット プロパティは「Visibility」(タイプ「Visibility」)

バインディングで ElementName の代わりに RelativeSource を設定すると:

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

次のエラーが表示されます。

System.Windows.Data エラー: 4 : 参照 'RelativeSource FindAncestor、AncestorType='System.Windows.Controls.ScrollViewer'、AncestorLevel='1'' でバインディングのソースが見つかりません。BindingExpression:Path=DataContext.MenuItemVisible; DataItem=null; ターゲット要素は 'MenuItem' (Name='') です。ターゲット プロパティは「Visibility」(タイプ「Visibility」)

4

1 に答える 1

5

ここで答えを見つけました:

したがって、ウィンドウの DataContext にアクセスするために必要だったのは次のとおりです。

Source={x:Reference Name=Root}

この場合に ElementName が機能しない理由については、こちらを参照してください。具体的には:

おそらく、継承コンテキスト リンクがない最も単純な例は、複数のランダムなプロパティ要素です。

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

ContextMenu は、Button の視覚的な子でも論理的な子でもなく、上記の継承コンテキスト ケースの 1 つでもありません (ContextMenu は Freezable ではありません)。

于 2012-06-13T14:54:44.163 に答える