Creating databound menu with sub-menus

Ribbon for WPF Forum

Posted 10 years ago by Phil Devaney - Senior Software Engineer, Serck Controls Ltd
Version: 4.5.0483
Avatar
I am trying to create a menu dynamicly using databinding, where the datasource is hierarchical with parent objects mapped onto sub-menus. I can get the menu created using DataTemplates, but the problem is the sub-menu only appears when the PopupButton in the parent menu is clicked instead of when moused over, and doesn't go away when the mouse moves away.

Here's my example XAML:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:r="http://schemas.actiprosoftware.com/winfx/xaml/ribbon"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="Window1" SizeToContent="WidthAndHeight"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">

  <Window.Resources>
    <DataTemplate DataType="{x:Type local:Foo}">
      <r:Button Context="MenuItem" Label="{Binding Name}" />
    </DataTemplate>

    <DataTemplate DataType="{x:Type local:Bar}">
      <r:Button Context="MenuItem" Label="{Binding Name}" />
    </DataTemplate>

    <DataTemplate DataType="{x:Type local:FooBar}">
      <r:PopupButton Context="MenuItem" Label="{Binding Name}">
        <r:PopupButton.PopupContent>
          <r:Menu ItemsSource="{Binding Bars}" />
        </r:PopupButton.PopupContent>
      </r:PopupButton>
    </DataTemplate>
  </Window.Resources>

  <StackPanel Orientation="Horizontal" Margin="50">
    <r:PopupButton Label="Databound Menu" Padding="10">
      <r:PopupButton.PopupContent>
        <r:Menu ItemsSource="{Binding Foos}" />
      </r:PopupButton.PopupContent>
    </r:PopupButton>
  </StackPanel>
</Window>
And my code-behind:

using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfApplication1
{
  public partial class Window1 : Window
  {
    public Window1()
    {
      InitializeComponent();
    }

    public IList<Foo> Foos
    {
      get
      {
        return new Foo[]
          {
            new Foo() { Name = "Foo 1" },
            new Foo() { Name = "Foo 2" },
            new FooBar() 
              { 
                Name = "FooBar 1",
                Bars = 
                  {
                    new Bar() { Name = "Bar 1" },
                    new Bar() { Name = "Bar 2" },
                  }
              },
            new Foo() { Name = "Foo 3" },
          };
      }
    }
  }

  public class Foo
  {
    public string Name { get; set; }
  }

  public class Bar
  {
    public string Name { get; set; }
  }

  public class FooBar : Foo
  {
    public FooBar()
    {
      this.Bars = new List<Bar>();
    }

    public List<Bar> Bars { get; private set; }
  }
}
I guess something needs to set IsPopupOpen = true on the PopupButton when IsMouseOver == true. I looked in the PopupButtonMenuItemSmallTemplate control template, but couldn't see any triggers to do this. I tried adding a trigger like this:

<r:PopupButton.Style>
  <Style>
    <Style.Triggers>
      <Trigger Property="r:PopupButton.IsMouseOver" Value="True">
        <Setter Property="r:PopupButton.IsPopupOpen" Value="True" />
      </Trigger>
    </Style.Triggers>
  </Style>
</r:PopupButton.Style>
but it doesn't work properly - the sub-menu appears, but when the mouse moves away from the parent item the entire menu disappears.

Phil

Comments (2)

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Phil,

When you use the PopupButton in a DataTemplate like that, the MenuItem (which is used as an item container) does not automatically bind the PopupButton.IsPopupOpen to it's own IsPopupOpen property.

You would need to explicitly bind them in your DataTemplate, something like:
<DataTemplate DataType="{x:Type local:FooBar}">
    <r:PopupButton Context="MenuItem" Label="{Binding Name}"
        IsPopupOpen="{Binding IsPopupOpen, RelativeSource={RelativeSource AncestorType={x:Type r:MenuItem}}, Mode=TwoWay}">
....
    </r:PopupButton>
</DataTemplate>
Hope this helps.


Actipro Software Support

Posted 10 years ago by Phil Devaney - Senior Software Engineer, Serck Controls Ltd
Avatar
That works perfectly, thanks!
The latest build of this product (v2018.1 build 0675) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.