none
Make a popup look like a ContextMenu?

    Question

  • I have an application where I want to have a popup show when a user clicks on a button.  I've been using the following XAML for this:

    <Popup Name="popAddChild" StaysOpen="False" PlacementTarget="{Binding ElementName=btnAddChild}" Placement="Bottom" > 
                <Menu> 
                    <Menu.ItemsPanel> 
                        <ItemsPanelTemplate> 
                            <StackPanel Orientation="Vertical" /> 
                        </ItemsPanelTemplate> 
                    </MenuItem.ItemsPanel> 
                    <Menu.ItemTemplate> 
                        <DataTemplate> 
                            <MenuItem Header="{Binding}" Command="..." CommandParameter="{Binding}" /> 
                        </DataTemplate> 
                    </Menu.ItemTemplate> 
                </Menu> 
            </Popup> 
            <Button x:Name="btnAddChild" Command="..."
                <!-- button info --> 
            </Button> 

    I want this popup to by styled the same as a ContextMenu or sub menu, but I have no idea how to do that.  Is there an easy way?

    Note, I can't use the Button's ContextMenu to do this, because there's no way for me to get the command bindings to work (yes, I have tried to change the Commandtarget, but that does not help.)
    Wednesday, September 17, 2008 4:03 PM

Answers

  • This is probably because I'm making the button work like a split button (as shown here: http://blogs.msdn.com/llobo/archive/2006/10/25/Split-Button-in-WPF.aspx) as just as a context menu it seems to work (even without the command target).

    XAML
    <Window x:Class="ContextMenuTest.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:local="clr-namespace:ContextMenuTest" 
        Title="Window1" Height="300" Width="300"
        <DockPanel> 
            <ToolBarTray DockPanel.Dock="Top"
                <ToolBar> 
                    <Button x:Name="btnAddChild" Command="{x:Static local:Window1.AddChildCommand}"
                        <TextBlock>Add</TextBlock> 
                        <Button.ContextMenu> 
                            <ContextMenu> 
                                <MenuItem Command="{x:Static local:Window1.AddChildCommand}" Header="Item1" CommandParameter="One" 
                                          CommandTarget="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/> 
                                <MenuItem Command="{x:Static local:Window1.AddChildCommand}" Header="Item1" CommandParameter="Two" 
                                          CommandTarget="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/> 
                            </ContextMenu> 
                        </Button.ContextMenu> 
                    </Button> 
                    <Button Command="{x:Static local:Window1.RemoveChildCommand}"
                        <TextBlock>Remove</TextBlock> 
                    </Button> 
                </ToolBar> 
            </ToolBarTray> 
            <TreeView x:Name="tvTreeView" Grid.Column="0"
                <TreeView.CommandBindings> 
                    <CommandBinding Command="{x:Static local:Window1.AddChildCommand}" Executed="AddChild_Executed" CanExecute="AddChild_CanExecute" /> 
                    <CommandBinding Command="{x:Static local:Window1.RemoveChildCommand}" Executed="RemoveChild_Executed" CanExecute="RemoveChild_CanExecute" /> 
                </TreeView.CommandBindings> 
                <TreeViewItem Header="Root"
                    <TreeViewItem Header="Can Add To" /> 
                    <TreeViewItem Header="Can Add Multi" /> 
                    <TreeViewItem Header="Can Remove" /> 
                    <TreeViewItem Header="Noting" /> 
                </TreeViewItem> 
            </TreeView> 
        </DockPanel> 
    </Window> 

    Code behind
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Data; 
    using System.Windows.Documents; 
    using System.Windows.Input; 
    using System.Windows.Media; 
    using System.Windows.Media.Imaging; 
    using System.Windows.Navigation; 
    using System.Windows.Shapes; 
     
    namespace ContextMenuTest 
        /// <summary> 
        /// Interaction logic for Window1.xaml 
        /// </summary> 
        public partial class Window1 : Window 
        { 
            public static RoutedCommand AddChildCommand = new RoutedCommand(); 
            public static RoutedCommand RemoveChildCommand = new RoutedCommand(); 
     
            public Window1() 
            { 
                InitializeComponent(); 
            } 
     
            private void AddChild_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
            { 
                if (tvTreeView != null
                { 
                    TreeViewItem item = tvTreeView.SelectedItem as TreeViewItem; 
                    Console.WriteLine(item); 
                    if (item != null
                        e.CanExecute = ((string)item.Header).Contains("Add"); 
                } 
            } 
     
            private void RemoveChild_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
            { 
                e.CanExecute = true
            } 
     
            private void AddChild_Executed(object sender, ExecutedRoutedEventArgs e) 
            { 
                TreeViewItem item = tvTreeView.SelectedItem as TreeViewItem; 
                if (((string)item.Header).Contains("Multi") && e.Parameter == null
                { 
                    btnAddChild.ContextMenu.IsOpen = true
                } 
            } 
     
            private void RemoveChild_Executed(object sender, ExecutedRoutedEventArgs e) 
            { 
     
            } 
        } 
     
         
     

    • Marked as answer by Marco Zhou Wednesday, September 24, 2008 9:36 AM
    Tuesday, September 23, 2008 6:27 PM

All replies

  • -> Note, I can't use the Button's ContextMenu to do this, because there's no way for me to get the command bindings to work (yes, I have tried to change the Commandtarget, but that does not help.)

    Have you tried the suggestion I made in the following thread to see if it works for you?
    http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7bd75a7c-eab4-4f3a-967b-94a9534a7455

    Thanks
    • Proposed as answer by Jim Zhou - MSFT Monday, September 22, 2008 11:21 AM
    • Unproposed as answer by Marco Zhou Tuesday, September 23, 2008 2:53 AM
    Monday, September 22, 2008 9:03 AM
  • Yes I have.  I believe because of the way I determine whether the command can be executed, the context menu just doesn't wok.
    Monday, September 22, 2008 2:43 PM
  • ->  I believe because of the way I determine whether the command can be executed, the context menu just doesn't wok.

    Okay, then could you please provide a small, complete and ready-to-run example to demonstrate how you "determine whether the command can be executed"?

    Thanks
    Tuesday, September 23, 2008 2:54 AM
  • This is probably because I'm making the button work like a split button (as shown here: http://blogs.msdn.com/llobo/archive/2006/10/25/Split-Button-in-WPF.aspx) as just as a context menu it seems to work (even without the command target).

    XAML
    <Window x:Class="ContextMenuTest.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:local="clr-namespace:ContextMenuTest" 
        Title="Window1" Height="300" Width="300"
        <DockPanel> 
            <ToolBarTray DockPanel.Dock="Top"
                <ToolBar> 
                    <Button x:Name="btnAddChild" Command="{x:Static local:Window1.AddChildCommand}"
                        <TextBlock>Add</TextBlock> 
                        <Button.ContextMenu> 
                            <ContextMenu> 
                                <MenuItem Command="{x:Static local:Window1.AddChildCommand}" Header="Item1" CommandParameter="One" 
                                          CommandTarget="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/> 
                                <MenuItem Command="{x:Static local:Window1.AddChildCommand}" Header="Item1" CommandParameter="Two" 
                                          CommandTarget="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/> 
                            </ContextMenu> 
                        </Button.ContextMenu> 
                    </Button> 
                    <Button Command="{x:Static local:Window1.RemoveChildCommand}"
                        <TextBlock>Remove</TextBlock> 
                    </Button> 
                </ToolBar> 
            </ToolBarTray> 
            <TreeView x:Name="tvTreeView" Grid.Column="0"
                <TreeView.CommandBindings> 
                    <CommandBinding Command="{x:Static local:Window1.AddChildCommand}" Executed="AddChild_Executed" CanExecute="AddChild_CanExecute" /> 
                    <CommandBinding Command="{x:Static local:Window1.RemoveChildCommand}" Executed="RemoveChild_Executed" CanExecute="RemoveChild_CanExecute" /> 
                </TreeView.CommandBindings> 
                <TreeViewItem Header="Root"
                    <TreeViewItem Header="Can Add To" /> 
                    <TreeViewItem Header="Can Add Multi" /> 
                    <TreeViewItem Header="Can Remove" /> 
                    <TreeViewItem Header="Noting" /> 
                </TreeViewItem> 
            </TreeView> 
        </DockPanel> 
    </Window> 

    Code behind
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Data; 
    using System.Windows.Documents; 
    using System.Windows.Input; 
    using System.Windows.Media; 
    using System.Windows.Media.Imaging; 
    using System.Windows.Navigation; 
    using System.Windows.Shapes; 
     
    namespace ContextMenuTest 
        /// <summary> 
        /// Interaction logic for Window1.xaml 
        /// </summary> 
        public partial class Window1 : Window 
        { 
            public static RoutedCommand AddChildCommand = new RoutedCommand(); 
            public static RoutedCommand RemoveChildCommand = new RoutedCommand(); 
     
            public Window1() 
            { 
                InitializeComponent(); 
            } 
     
            private void AddChild_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
            { 
                if (tvTreeView != null
                { 
                    TreeViewItem item = tvTreeView.SelectedItem as TreeViewItem; 
                    Console.WriteLine(item); 
                    if (item != null
                        e.CanExecute = ((string)item.Header).Contains("Add"); 
                } 
            } 
     
            private void RemoveChild_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
            { 
                e.CanExecute = true
            } 
     
            private void AddChild_Executed(object sender, ExecutedRoutedEventArgs e) 
            { 
                TreeViewItem item = tvTreeView.SelectedItem as TreeViewItem; 
                if (((string)item.Header).Contains("Multi") && e.Parameter == null
                { 
                    btnAddChild.ContextMenu.IsOpen = true
                } 
            } 
     
            private void RemoveChild_Executed(object sender, ExecutedRoutedEventArgs e) 
            { 
     
            } 
        } 
     
         
     

    • Marked as answer by Marco Zhou Wednesday, September 24, 2008 9:36 AM
    Tuesday, September 23, 2008 6:27 PM