簡體   English   中英

WPF TreeViewItem上下文菜單使用HierarchicalDataTemplate取消突出顯示項目

[英]WPF TreeViewItem Context Menu Unhighlights Item With HierarchicalDataTemplate

我有與此問題相同的問題,我希望TreeViewItem在顯示其上下文菜單時仍看起來處於主動選擇狀態。 但是,在我的樹中,每個級別都有一個不同類型的對象,因此我希望每個級別都有一個不同的ContextMenu。 我正在使用HierachicalDataTemplate完成此操作。 所以我有以下XAML:

<Window x:Class="Project.MainWindow">
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Project" ContentRendered="Window_ContentRendered">
    <Grid>
        <Grid.Resources>
            <DataTemplate x:Key="VolumeTemplate">
                <StackPanel Orientation="Horizontal">
                    <Image Source="{StaticResource VolumeIcon}" Margin="3,3,3,3" />
                    <TextBlock Text="{Binding Path=Name}" Margin="3,3,3,3">
                        <TextBlock.ContextMenu>
                            <ContextMenu>
                                <MenuItem Command="{Binding VolumeTestCommand}"
                                          Header="VolumeTest" />
                            </ContextMenu>
                        </TextBlock.ContextMenu>
                    </TextBlock>
                </StackPanel>
            </DataTemplate>
            <HierachicalDataTemplate x:Key="ServerTemplate"
                                     ItemsSource="{Binding Volumes}"
                                     ItemTemplate="{StaticResource VolumeTemplate}">
                <StackPanel Orientation="Horizontal">
                    <Image Source="{StaticResource ServerIcon}" Margin="3,3,3,3" />
                    <TextBlock Text="{Binding Name}" Margin="3,3,3,3" >
                        <TextBlock.ContextMenu>
                            <ContextMenu>
                                <MenuItem Command="{Binding ServerTestCommand}"
                                          Header="ServerTest" />
                            </ContextMenu>
                        </TextBlock.ContextMenu>
                    </TextBlock>
                </StackPanel>
            </HierarchicalDataTemplate>
        </Grid.Resources>
        <TreeView HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                  ItemsSource="{Binding Servers}" Name="tvMain"
                  ItemTemplate="{StaticResource ServerTemplate}"
                  PreviewMouseRightButtonDown="tvMain_PreviewMouseRightButtonDown" />
    </Grid>
</Window>

后面的代碼:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_ContentRendered(object sender, EventArgs e)
    {
        //set DataContext here, based on a login dialog
    }

    static T VisualUpwardSearch<T>(DependencyObject source) where T : DependencyObject
    {
        DependencyObject returnVal = source;

        while (returnVal != null && !(returnVal is T))
        {
            if (returnVal is Visual || returnVal is Visual3D)
            {
                returnVal = VisualTreeHelper.GetParent(returnVal);
            }
            else
            {
                returnVal = LogicalTreeHelper.GetParent(returnVal);
            }
        }

        return returnVal as T;
    }

    private void tvMain_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        TreeViewItem treeViewItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject);

        if(treeViewItem != null)
        {
            treeViewItem.IsSelected = true;
            e.Handled = true;
        }
    }
}

我嘗試了所引用問題的答案,但我認為它不起作用,因為上下文菜單位於TextBlock而不是TreeViewItem上。 有沒有一種方法可以將ContextMenu附加到DataTemplate中的TreeViewItem上,或者有其他方法可以解決此問題?

我最終不得不創建一個附加屬性,該屬性將上下文菜單從TextBlock移至TreeViewItem:

public static readonly DependencyProperty StealContextMenuProperty = 
    DependencyProperty.RegisterAttached(
        "StealContextMenu", 
        typeof(bool), 
        typeof(ParentClass),
        new UIPropertyMetadata(false, new PropertyChangedCallback(SCMChanged))
    );

public static bool GetStealContextMenu(FrameworkElement obj)
{
    return (bool)obj.GetValue(StealContextMenuProperty);
}

public static void SetStealContextMenu(FrameworkElement obj, bool value)
{
    obj.SetValue(StealContextMenuProperty, value);
}

public static void SCMChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    FrameworkElement fe = sender as FrameworkElement;
    if (fe == null) return;

    bool value = (bool)e.NewValue;
    if (!value) return;

    fe.Loaded += new RoutedEventHandler(fe_Loaded);
}

public static void fe_Loaded(object sender, RoutedEventArgs e)
{
    FrameworkElement fe = (FrameworkElement)sender;
    FrameworkElement child;
    child = VisualDownwardSearch<FrameworkElement>(fe, x => x.ContextMenu != null);
    if (child != null)
    {
        fe.ContextMenu = child.ContextMenu;
        child.ContextMenu = null;
    }
}

public static T VisualDownwardSearch<T>(T source, Predicate<T> match)
    where T : DependencyObject
{
    Queue<DependencyObject> queue = new Queue<DependencyObject>();
    queue.Enqueue(source);
    while(queue.Count > 0)
    {
        DependencyObject dp = queue.Dequeue();

        if (dp is Visual || dp is Visual3D)
        {
            int childrenCount = VisualTreeHelper.GetChildrenCount(dp);
            for (int i = 0; i < childrenCount; i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(dp, i);
                if (child is T)
                {
                    T tChild = (T)child;
                    if (match(tChild)) return tChild;
                }
                queue.Enqueue(child);
            }
        }
        else
        {
            foreach (DependencyObject child in LogicalTreeHelper.GetChildren(dp))
            {
                if (child is T)
                {
                    T tChild = (T)child;
                    if (match(tChild)) return tChild;
                }
                queue.Enqueue(child);                    
            }
        }
    }
    return null;      
}

暫無
暫無

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

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