ContextMenu StaysOpen不起作用

时间:2013-12-03 12:31:47

标签: wpf

我在UserControl内显示ContextMenu。此外,UserControl我正在展示一个包含一些按钮和数据网格的PopupPopup中的所有数据都在运行时加载。

问题是ContextMenu忽略属性StaysOpen,即使它已设置为true

Popup确实保持打开状态,但我在后面的代码中将StaysOpen设置为true,但ContextMenu没有。{/ p>

我尝试使用以下代码:

<UserControl x:Class="UserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Grid>
   <Popup Name="popupState" PlacementTarget="{Binding ElementName=txtSearch}" PopupAnimation="Slide" Placement="Bottom" Focusable="True" AllowsTransparency="True" VerticalAlignment="Top">

   <Button HorizontalAlignment="Right" Margin="5" Background="GhostWhite" Name="btnSelectAll" Click="btnSelectAll_Click" Width="30" Height="30">

   <my:DataGrid VerticalAlignment="Stretch" MaxHeight="300" VerticalScrollBarVisibility="Auto" RowHeaderWidth="0" Margin="5,5,5,1" Background="White" HorizontalAlignment="Stretch" Name="DGTeamCommunicator" HorizontalContentAlignment="Left" HorizontalGridLinesBrush="#D6D7D6" GridLinesVisibility="None">
      <my:DataGridTemplateColumn  Width="Auto" MinWidth="30">
         <my:DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
               <StackPanel Orientation="Horizontal" ContextMenuService.IsEnabled="True" ContextMenuService.HasDropShadow="True">
                  <Button Name="btnCall"  Click="btnCall_Click" ContextMenuService.IsEnabled="True">
                  </Button>
               </StackPanel>
           </DataTemplate>
        </my:DataGridTemplateColumn.CellTemplate>
      </my:DataGridTemplateColumn>
   </my:DataGrid>
</Popup>

我的要求是在点击Popup中的按钮时阻止ContextMenu以及Popup关闭。

请为我提供解决方案。

1 个答案:

答案 0 :(得分:0)

坏消息是这种行为是设计的。 ContextMenu被定义为显示几个菜单,当其中一个菜单被点击时,ContextMenu在内部将IsOpen设置为false。

好消息是行为应该保持不变,对于任何其他自定义,您应该使用Popup而不是ContextMenu。但是,如果您必须使用ContextMenu,无论出于何种原因,这是一种解决方法:

<StackPanel>
    <Button>
        Popup Demo
        <Button.ContextMenu>
            <local:StaysOpenContextMenu x:Name="ContextMenu1" StaysOpen="True">
                <StackPanel>
                    <TextBox x:Name="TextBox1" Width="100" TextChanged="OnTextChanged"/>
                    <Popup x:Name="Popup1" Placement="Bottom" PlacementTarget="{Binding ElementName=tbx}" StaysOpen="True">
                        <Button Content="click me"/>
                    </Popup>
                </StackPanel>
            </local:StaysOpenContextMenu>
        </Button.ContextMenu>
    </Button>
    <Button Click="OnClick">Close Popup</Button>
</StackPanel>

您需要自定义ContextMenu来完成工作:

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

    private void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        this.Popup1.IsOpen = true;
    }

    private void OnClick(object sender, RoutedEventArgs e)
    {
        this.Popup1.IsOpen = false;
        this.ContextMenu1.CloseContextMenu();
    }
}

public class StaysOpenContextMenu : ContextMenu
{
    private bool mustStayOpen;

    static StaysOpenContextMenu()
    {
        IsOpenProperty.OverrideMetadata(
            typeof(StaysOpenContextMenu),
            new FrameworkPropertyMetadata(false, null, CoerceIsOpen));
        StaysOpenProperty.OverrideMetadata(
            typeof(StaysOpenContextMenu),
            new FrameworkPropertyMetadata(false, PropertyChanged, CoerceStaysOpen));
    }

    private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        StaysOpenContextMenu menu = (StaysOpenContextMenu)d;
        menu.mustStayOpen = (bool)e.NewValue;
    }

    private static object CoerceStaysOpen(DependencyObject d, object basevalue)
    {
        d.CoerceValue(IsOpenProperty);
        return basevalue;
    }

    private static object CoerceIsOpen(DependencyObject d, object basevalue)
    {
        StaysOpenContextMenu menu = (StaysOpenContextMenu)d;
        if (menu.StaysOpen && menu.mustStayOpen)
        {
            return true;
        }

        return basevalue;
    }

    public void CloseContextMenu()
    {
        this.mustStayOpen = false;
        this.IsOpen = false;
    }
}