xceedsoftware / wpftoolkit

All the controls missing in WPF. Over 1 million downloads.
Other
3.87k stars 872 forks source link

DropDownButton closes when popup child try open own context menu #1712

Open vitidev opened 2 years ago

vitidev commented 2 years ago

If the child element of the popup has its own context menu

<xctk:DropDownButton
    Width="100"
    Height="30"
    Content="test">
    <xctk:DropDownButton.DropDownContent>
        <StackPanel
            Width="150"
            Height="300"
            HorizontalAlignment="Stretch">
            <StackPanel Height="50" Background="Red">
                <StackPanel.ContextMenu>
                    <ContextMenu>
                        <MenuItem CommandParameter="{Binding}" Header="test" />
                    </ContextMenu>
                </StackPanel.ContextMenu>
            </StackPanel>
        </StackPanel>
    </xctk:DropDownButton.DropDownContent>
</xctk:DropDownButton>

then when try to open this menu, everything disappears due to method

protected override void OnIsKeyboardFocusWithinChanged( DependencyPropertyChangedEventArgs e )
{
  base.OnIsKeyboardFocusWithinChanged( e );
  if( !( bool )e.NewValue )
  {
    this.CloseDropDown( false );
  }
}

maybe let it take allow the opening of child menu something like this

protected override void OnIsKeyboardFocusWithinChanged( DependencyPropertyChangedEventArgs e )
{
  base.OnIsKeyboardFocusWithinChanged( e );
  if( !( bool )e.NewValue )
  {
    var contextMenu = GetInnerOpenedContextMenuFromPopup(_popup.Child);
    if (contextMenu == null)
      this.CloseDropDown(false);
    else
    {
      RoutedEventHandler handler = null;
      handler = new RoutedEventHandler((s, a) =>
      {
        contextMenu.Closed -= handler;
        if (!IsKeyboardFocusWithin)
          this.CloseDropDown(false);
      });
      contextMenu.Closed += handler;
    }
  }
}

private static ContextMenu GetInnerOpenedContextMenuFromPopup(DependencyObject parent)
{
  if (parent == null)
    throw new ArgumentNullException(nameof(parent));

  var queue = new Queue<DependencyObject>(new[] { parent });

  while (queue.Any())
  {
    var reference = queue.Dequeue();
    var count = VisualTreeHelper.GetChildrenCount(reference);

    for (var i = 0; i < count; i++)
    {
      var child = VisualTreeHelper.GetChild(reference, i);
      if (child is FrameworkElement children && children.ContextMenu != null && children.ContextMenu.IsOpen)
        return children.ContextMenu;

      queue.Enqueue(child);
    }
  }

  return null;
}
XceedBoucherS commented 2 years ago

Thank you, We will have a look.

evancekafando commented 2 years ago

Hi

The issue has been fixed. It will be made availlable in v4.5

Thank you.

zhongruijia commented 2 years ago

这里是郭瑞的邮箱,已收到您的来件,我会尽快拜阅并给予您回复