Creating Databound ContextMenu

Ribbon for WPF Forum

Posted 8 years ago by Keith I
Version: 11.2.0551
Platform: .NET 4.0
Environment: Windows 7 (64-bit)
Avatar
Hi,

When displaying a context menu that is bound to a collection of view-model classes I receive an null-reference exception.

I have used the code from here but changed the popup-menu to a context menu.

Here is the xaml:

<Window x:Class="WpfApplication2.MainWindow"
        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:WpfApplication2"
        Title="MainWindow" 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>

    <TextBlock Margin="50" Text="Right-click here">
        <TextBlock.ContextMenu>
            <r:ContextMenu ItemsSource="{Binding Foos}"/>
        </TextBlock.ContextMenu>
    </TextBlock>

    <!--<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 the code-behind:

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

namespace WpfApplication2
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            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 receive the null-reference exception when I right-click. The exception stack-trace is:

Quote:

at System.Windows.Controls.ItemContainerGenerator.LinkContainerToItem(DependencyObject container, Object item, Boolean isRecycled)
at System.Windows.Controls.ItemContainerGenerator.Generator.GenerateNext(Boolean stopAtRealized, Boolean& isNewlyRealized)
at System.Windows.Controls.ItemContainerGenerator.System.Windows.Controls.Primitives.IItemContainerGenerator.GenerateNext()
at System.Windows.Controls.Panel.GenerateChildren()
at System.Windows.Controls.Panel.EnsureGenerator()
at System.Windows.Controls.Panel.get_InternalChildren()
at System.Windows.Controls.StackPanel.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
at System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
at System.Windows.Controls.ScrollContentPresenter.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Border.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.ScrollViewer.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Border.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Decorator.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.DockPanel.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Documents.AdornerDecorator.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Control.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Documents.AdornerDecorator.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Decorator.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Primitives.PopupRoot.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Interop.HwndSource.SetLayoutSize()
at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
at System.Windows.Interop.HwndSource.set_RootVisual(Visual value)
at System.Windows.Controls.Primitives.Popup.SetRootVisualToPopupRoot()
at System.Windows.Controls.Primitives.Popup.CreateWindow(Boolean asyncCall)
at System.Windows.Controls.Primitives.Popup.OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
at System.Windows.Data.BindingOperations.SetBinding(DependencyObject target, DependencyProperty dp, BindingBase binding)
at System.Windows.Controls.Primitives.Popup.CreateRootPopup(Popup popup, UIElement child)
at System.Windows.Controls.ContextMenu.HookupParentPopup()
at System.Windows.Controls.ContextMenu.OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.DependencyObject.SetCurrentValueInternal(DependencyProperty dp, Object value)
at System.Windows.Controls.PopupControlService.RaiseContextMenuOpeningEvent(IInputElement source, Double x, Double y, Boolean userInitiated)
at System.Windows.Controls.PopupControlService.ProcessMouseUp(Object sender, MouseButtonEventArgs e)
at System.Windows.Controls.PopupControlService.OnPostProcessInput(Object sender, ProcessInputEventArgs e)
at System.Windows.Input.InputManager.RaiseProcessInputEventHandlers(ProcessInputEventHandler postProcessInput, ProcessInputEventArgs processInputEventArgs)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at System.Windows.Application.Run()
at WpfApplication2.App.Main() in c:\users\keith.iveson\documents\visual studio 2010\Projects\WpfApplication2\obj\x86\Debug\App.g.cs:line 0
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()


The context menu works OK if I change:
<r:ContextMenu
to:
<ContextMenu
Keith

Comments (1)

Posted 8 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Keith,

If you do this instead it will show up:
<TextBlock.ContextMenu>
    <ribbon:ContextMenu>
        <ribbon:Menu ItemsSource="{Binding Foos}"/>
    </ribbon:ContextMenu>
</TextBlock.ContextMenu>
Our context menu is designed to hold multiple types of content but to get the menu look you need to put a ribbon:Menu control in it.

Still if you are using 2011.2 and are just doing basic menu items you should probably use the native WPF context menus instead since we theme those in Themes 2011.2 if you have native control theming active. And they'd look the same as ribbon:Buttons in a menu in that case.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.