我正在使用C#和WPF,我不知道如何完成以下任务:
我有一个TreeView,它包含TreeViewItems。在每个TreeViewItem.Header中,都有一个Stack Panel,其中包含一个图标,一个文本和一个ContextMenu(cotext菜单在TreeView.Resources中定义。当用户右键单击堆栈面板时,会显示上下文菜单,其中包含一个MenuItem。在该MenuItem的Click事件中,创建了一个自定义对话框,该对话框需要对打开该上下文菜单的TreeViewItem的引用。我如何获得该引用?
以下是定义树视图的XAML代码:
<TreeView Grid.Row="1" Margin="5, 3, 5, 3">
<TreeView.Resources>
<ContextMenu x:Key="RoomsContextMenu">
<MenuItem Header="Add Rooms" VerticalAlignment="Bottom" Click="addRom_Click">
<MenuItem.Icon>
<Image Width="20" Height="20" Source="/GroupAddressCreatorWPF;component/Images/add.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</TreeView.Resources>
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal" ContextMenu="{StaticResource RoomsContextMenu}">
<Image Width="5" Height="5" Margin="3,0"
Source="/GroupAddressCreatorWPF;component/Images/red.png" />
<TextBlock Text="Main area 1" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
</TreeView>
这是创建自定义对话框的菜单项中的click事件实现,以及我需要访问TreeViewItem的位置:
private void addRom_Click(object sender, RoutedEventArgs e)
{
AddRoomsDialog roomsDialog = new AddRoomsDialog(???);
roomsDialog.Show();
}
答案 0 :(得分:1)
谢谢lenkan。 我不得不修改我的XAML文件,以便用户能够在树视图中删除子项。现在我的XAML文件如下所示:
<TreeView.Resources>
<ContextMenu x:Key="RoomsContextMenu">
<MenuItem Header="Add Rooms" VerticalAlignment="Bottom" Click="addRom_Click">
<MenuItem.Icon>
<Image Width="20" Height="20" Source="/GroupAddressCreatorWPF;component/Images/add.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
<HierarchicalDataTemplate DataType="{x:Type local:MainArea}" ItemsSource="{Binding Path=RoomCollection}">
<Border Width="150" BorderBrush="RoyalBlue" BorderThickness="1" CornerRadius="2" Margin="2" Padding="2" >
<StackPanel Orientation="Horizontal" ContextMenu="{StaticResource RoomsContextMenu}">
<Image Width="10" Height="10" Margin="3,0"
Source="/GroupAddressCreatorWPF;component/Images/blue.png" />
<TextBlock Text="{Binding MainAreaName}" />
</StackPanel>
</Border>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Room}">
<Border Width="132" BorderBrush="Green" BorderThickness="1" CornerRadius="2" Margin="1" >
<StackPanel Orientation="Horizontal">
<Image Width="10" Height="10" Margin="3,0"
Source="/GroupAddressCreatorWPF;component/Images/green.png" />
<TextBlock Text="{Binding RoomName}" />
</StackPanel>
</Border>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
问题现在出现在这段代码中:
roomsTreeView.ContextMenuOpening += (senderContextMenu, eContextMenu) =>
{
mMainAreaItem = ((TreeView)senderContextMenu).Items.OfType<TreeViewItem>().FirstOrDefault(item => item.IsMouseOver);
};
由于树视图中的项不是TreeViewItem(它们是MainArea),因此上述代码中的mMainAreaItem始终为-1。我也尝试过以下方法:
roomsTreeView.ContextMenuOpening += (senderContextMenu, eContextMenu) =>
{
mMainAreaItem = ((TreeView)senderContextMenu).Items.OfType<MainArea>().FirstOrDefault(item => item.IsMouseOver);
};
但由于MainArea不包含IsMouseOver属性,因此无法编译。这是解决这个问题的简单方法吗? (对不起,我对C#和WPF很陌生。)
答案 1 :(得分:0)
将名称添加到TreeView,以便通过实例字段访问它。
<TreeView Margin="5, 3, 5, 3" x:Name="TreeView">
然后,在您的控件或窗口构造函数中,侦听ContextMenuOpening和ContextMenuClosing事件,以将当前活动项存储在实例字段的树视图中。然后,您可以在单击事件处理程序中访问它。
private TreeViewItem activeItem;
public Window()
{
InitializeComponent();
// sender is the TreeView itself. Just iterate through the items
// and retrieve the first one where IsMouseOver returns true.
TreeView.ContextMenuOpening += (sender, e) =>
{
activeItem = ((TreeView) sender).Items.OfType<TreeViewItem>().FirstOrDefault(item => item.IsMouseOver);
};
TreeView.ContextMenuClosing += (o, e) =>
{
activeItem = null;
};
}
private void addRom_Click(object sender, RoutedEventArgs e)
{
// Once we get here, activeItem will reference the TreeViewItem
// that was under the cursor when the context menu was opened.
AddRoomsDialog roomsDialog = new AddRoomsDialog(activeItem);
roomsDialog.Show();
}
或者, ContextMenuOpening 事件处理程序中的RoutedEventArgs e 变量将保存对单击的项的引用。即,TextBlock或Image。如果适用于您的问题,您可以存储对该对象的引用。