从子 XAML 检索树视图项的数据上下文
本文关键字:数据 上下文 视图 XAML 检索树 从子 | 更新日期: 2023-09-27 18:34:36
我有一个DataBound树视图,从中创建/显示树视图项并具有上下文菜单。这是正常工作的。然后,我尝试使用自定义菜单项类,以便可以通过从上下文菜单触发的命令检索树视图项的数据上下文。抱歉,如果这令人困惑。我可能这样做走错了路。
这是我的 xaml。
<UserControl x:Class="Pipeline_General.Custom_Controls.ProjectTree"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:pm="clr-namespace:Pipeline_General"
mc:Ignorable="d"
DataContext = "{Binding RelativeSource={RelativeSource Self}}"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TreeView Name="StructureTree" Background="{x:Static pm:myBrushes.defaultBG}" ItemsSource="{Binding ProjectList}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
<Setter Property="Margin" Value="5,5,5,5" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Background="{x:Static pm:myBrushes.defaultBG}" Foreground="{x:Static pm:myBrushes.gray}">
<pm:ProjectTreeMenuItem Header="Add Episode.."
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.AddEpCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
<pm:ProjectTreeMenuItem Header="Add Sequence.."
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.AddSeqCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
<pm:ProjectTreeMenuItem Header="Add Scene.."
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.AddScCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type pm:ProjectRoot}" ItemsSource="{Binding Episodes}">
<TextBlock Text="{Binding Path=Title}" Foreground="{x:Static pm:myBrushes.pink}"
FontFamily="Calibri" FontSize="18"/>
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
<Setter Property="Margin" Value="5,5,5,5" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Background="{x:Static pm:myBrushes.defaultBG}" Foreground="{x:Static pm:myBrushes.gray}">
<pm:ProjectTreeMenuItem Header="Add Sequence.."
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.AddSeqCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
<pm:ProjectTreeMenuItem Header="Add Scene.."
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.AddScCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
<Separator Height="15" Margin="20,0"/>
<pm:ProjectTreeMenuItem Header="Cut"
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.CutCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
<pm:ProjectTreeMenuItem Header="Un-Cut"
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.UnCutCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type pm:Episode}" ItemsSource="{Binding Sequences}">
<TextBlock Text="{Binding Path=Key}" Foreground="{x:Static pm:myBrushes.yellow}"
FontFamily="Calibri" FontSize="14"/>
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
<Setter Property="Margin" Value="5,5,5,5" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Background="{x:Static pm:myBrushes.defaultBG}" Foreground="{x:Static pm:myBrushes.gray}">
<pm:ProjectTreeMenuItem Header="Add Scene.."
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.AddScCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
<Separator Height="15" Margin="20,0"/>
<pm:ProjectTreeMenuItem Header="Cut"
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.CutCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
<pm:ProjectTreeMenuItem Header="Un-Cut"
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.UnCutCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type pm:Sequence}" ItemsSource="{Binding Scenes}">
<TextBlock Text="{Binding Path=Key}" Foreground="{x:Static pm:myBrushes.yellow}"
FontFamily="Calibri" FontSize="14"/>
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Background="{x:Static pm:myBrushes.defaultBG}" Foreground="{x:Static pm:myBrushes.gray}">
<pm:ProjectTreeMenuItem Header="Cut"
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.CutCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
<pm:ProjectTreeMenuItem Header="Un-Cut"
Element="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}"
Command="{x:Static pm:MyCommands.UnCutCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Margin="20,0"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
以及我的自定义菜单项类和命令。
public static class MyCommands
{
static MyCommands()
{
AddEpCommand = new SimpleDelegateCommand(p =>
{
var menuItem = p as ProjectTreeMenuItem;
var Element = menuItem.Element as ProjectElement;
Console.WriteLine(Element.Key);
Console.WriteLine("EP");
});
AddSeqCommand = new SimpleDelegateCommand(p =>
{
var menuItem = p as ProjectTreeMenuItem;
var Element = menuItem.Element as ProjectElement;
Console.WriteLine(Element.Key);
Console.WriteLine("SEQ");
});
AddScCommand = new SimpleDelegateCommand(p =>
{
var menuItem = p as ProjectTreeMenuItem;
var Element = menuItem.Element as ProjectElement;
Console.WriteLine(Element.Key);
Console.WriteLine("SC");
});
CutCommand = new SimpleDelegateCommand(p =>
{
var menuItem = p as ProjectTreeMenuItem;
var Element = menuItem.Element as ProjectElement;
Console.WriteLine(Element.Key);
Console.WriteLine("SC");
});
UnCutCommand = new SimpleDelegateCommand(p =>
{
var menuItem = p as ProjectTreeMenuItem;
var Element = menuItem.Element as ProjectElement;
Console.WriteLine(Element.Key);
Console.WriteLine("SC");
});
}
public static ICommand AddEpCommand { get; set; }
public static ICommand AddSeqCommand { get; set; }
public static ICommand AddScCommand { get; set; }
public static ICommand CutCommand { get; set; }
public static ICommand UnCutCommand { get; set; }
}
public class SimpleDelegateCommand : ICommand
{
public SimpleDelegateCommand(Action<object> executeAction)
{
_executeAction = executeAction;
}
private Action<object> _executeAction;
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_executeAction(parameter);
}
}
public class ProjectTreeMenuItem : MenuItem
{
#region Element (DependencyProperty)
public ProjectElement Element
{
get { return (ProjectElement)GetValue(ElementProperty); }
set { SetValue(ElementProperty, value); }
}
public static readonly DependencyProperty ElementProperty =
DependencyProperty.Register("Element", typeof(ProjectElement), typeof(ProjectTreeMenuItem),
new PropertyMetadata { PropertyChangedCallback = ElementChanged });
private static void ElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ProjectTreeMenuItem so = d as ProjectTreeMenuItem;
if (so != null && e.NewValue != null)
{
so.Element = (ProjectElement)e.NewValue;
Console.WriteLine("HERE " + so.Element.Title);
}
}
#endregion
public ProjectTreeMenuItem()
:base()
{
}
}
projectElement类(im在项目中的数百个其他地方使用(有一个字符串键,字符串标题属性,它在其他地方工作正常。我很确定我的问题在于通过数据上下文通过 xaml 设置元素属性。
最终想
通了。我使用了菜单项的命令属性,并使用它来直接发回数据上下文,而不是使用自定义菜单项类上的依赖项属性。
更大的问题是我试图使用从可视化树中查找祖先,这在上下文菜单中不起作用,而且我认为也因为我在层次结构数据模板中,它无论如何都不起作用。
不过,以下就可以解决问题。
<ContextMenu Background="{x:Static pm:myBrushes.defaultBG}" Foreground="{x:Static pm:myBrushes.gray}"
DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Add Episode.."
Command="{x:Static pm:MyCommands.AddEpCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.DataContext}"
Margin="20,0"/>
<MenuItem Header="Add Sequence.."
Command="{x:Static pm:MyCommands.AddSeqCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.DataContext}"
Margin="20,0"/>
<MenuItem Header="Add Scene.."
Command="{x:Static pm:MyCommands.AddScCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.DataContext}"
Margin="20,0"/>
</ContextMenu>