簡體   English   中英

從上下文菜單發送對父對象的引用

[英]Send a reference to a parent object from a context menu

我正在使用 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>

這是創建自定義對話框的菜單項中的單擊事件實現,我需要在其中訪問 TreeViewItem:

private void addRom_Click(object sender, RoutedEventArgs e)
{
    AddRoomsDialog roomsDialog = new AddRoomsDialog(???);
    roomsDialog.Show();
}

謝謝倫坎。 我不得不修改我的 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 還是很陌生)。

名稱添加到您的 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 或圖像。 如果這適用於您的問題,您可以存儲對該對象的引用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM