Everything in the code below works, except for binding to ContextMenu. This is obviously due to the fact that ContextMenu is inside a style that puts it in a different name pointer from the rest of xaml. I am looking for a solution where I do not need to create an instance of ContextMenu in the code, because the application in which I have to apply the solution contains a very large ContextMenu with a lot of bindings. There must be a way to do this in haml, otherwise it would look like serious oversight. Also note that I already tried traversing the element tree using VisualTreeHelper and LogicalTreeHelper, but I could not find the ContextMenu from the root Window element (these classes obviously missed the interesting elements). In any case, all of the code is below. This can be inserted into a new WPF application in Visual Studio, and nothing is missing.
Here is the code for App.xaml.cs (xaml remained unchanged):
using System.Windows; namespace WpfApplication1 {
Here's the haml for what was originally Window1:
<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>
Here is the codebehind for what was originally Window1:
using System.Windows; using System.Windows.Markup; namespace WpfApplication1 {
A new class has been added to a project called WindowVM. Here is his code:
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)); } } }
Any insight would be greatly appreciated. Many thanks!
Andrew
source share