【发布时间】:2010-06-06 19:14:37
【问题描述】:
除了 ContextMenu 上的绑定之外,以下代码中的所有内容都有效。这显然是因为 ContextMenu 位于 Style 内部,这将其置于与 xaml 的其余部分不同的名称范围内。我正在寻找一个解决方案,我不必在代码隐藏中实例化 ContextMenu,因为我必须应用该解决方案的应用程序包含一个非常大的 ContextMenu 和很多绑定。必须有一种方法可以在 xaml 中完成此操作,否则这似乎是一个严重的疏忽。另请注意,我已经尝试使用 VisualTreeHelper 和 LogicalTreeHelper 遍历元素树,但我无法从 Window 的根元素中找到 ContextMenu(这些类显然跳过了有趣的元素)。无论如何,所有代码都在下面。这可以粘贴到 Visual Studio 中的新 WPF 应用程序中,并且不会丢失任何内容。
这是 App.xaml.cs 的代码(xaml 保持不变):
using System.Windows;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
WindowV windowV = new WindowV();
WindowVM windowVM = new WindowVM();
windowV.DataContext = windowVM;
windowV.Show();
}
}
}
这是原来 Window1 的 xaml:
<Window x:Class="WpfApplication1.WindowV"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:WpfApplication1"
Name="MainWindow"
Title="WindowV" Height="300" Width="300">
<Window.Resources>
<Style TargetType="{x:Type ItemsControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsLocked}" Value="true">
<Setter Property="ItemsSource" Value="{Binding LockedList}" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding IsLocked}" Value="false">
<Setter Property="ItemsSource" Value="{Binding RegularList}" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding MenuItem1, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
<MenuItem Header="{Binding MenuItem2, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
<MenuItem Header="{Binding MenuItem3, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="4*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ItemsControl Grid.Row="0" />
<Button Name="ToggleButton"
Grid.Row="1"
Content="Toggle Lock"
Click="OnToggleLock" />
</Grid>
</Window>
这是最初 Window1 的代码隐藏:
using System.Windows;
using System.Windows.Markup;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class WindowV : Window
{
public WindowV()
{
InitializeComponent();
}
private void OnToggleLock(object sender, RoutedEventArgs e)
{
if (((WindowVM)(DataContext)).IsLocked == true)
((WindowVM)(DataContext)).IsLocked = false;
else
((WindowVM)(DataContext)).IsLocked = true;
}
}
}
在名为 WindowVM 的项目中添加了一个新类。这是它的代码:
using System.Collections.Generic;
using System.ComponentModel;
namespace WpfApplication1
{
public class WindowVM : INotifyPropertyChanged
{
public string MenuItem1
{
get
{
string str = "Menu item 1";
return str;
}
}
public string MenuItem2
{
get
{
string str = "Menu item 2";
return str;
}
}
public string MenuItem3
{
get
{
string str = "Menu item 3";
return str;
}
}
public List<string> LockedList
{
get
{
List<string> list = new List<string>();
list.Add("This items control is currently locked.");
return list;
}
}
public List<string> RegularList
{
get
{
List<string> list = new List<string>();
list.Add("Item number 1.");
list.Add("Item number 2.");
list.Add("Item number 3.");
return list;
}
}
private bool _isLocked;
public bool IsLocked
{
get { return _isLocked; }
set
{
if (_isLocked != value)
{
_isLocked = value;
OnPropertyChanged("IsLocked");
}
}
}
public WindowVM()
{
IsLocked = false;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
任何见解将不胜感激。非常感谢!
安德鲁
【问题讨论】:
-
编辑:好的,在这一点上,我什至在代码隐藏中遇到了困难。有什么想法吗?
-
在上面的问题中,我刚刚意识到我确实对 App.xaml 文件进行了一次调整。具体来说,我删除了包含启动 url 的行。除此之外,App.xaml 文件保持不变。否则,这些文件可以在 Visual Studio 中粘贴到新的 WPF 应用程序中,并且当应用程序运行时,右键单击的问题会很明显。
标签: wpf xaml binding contextmenu