简体   繁体   中英

wpf - Context menu - Reuse static resources within dynamic resources

I have a user control with resources as below:

<UserControl.Resources>

    <Image x:Key="IconPrinter" Source="/PrintViewerWPF;component/Resources/Images/printer.png" />

    <MenuItem x:Key="PrintDoc" 
              Header="Print" 
              Click="PrintDoc_OnClick"
              Icon="{StaticResource IconPrinter}" />

    <ContextMenu x:Key="MergedContextMenu">
        <StaticResource ResourceKey="PrintDoc"/>
    </ContextMenu>

    <ContextMenu x:Key="SingleContextMenu">
        <StaticResource ResourceKey="PrintDoc"/>
    </ContextMenu>

    <DataTemplate x:Key="mergedDocDisplayGrid">
        <StackPanel StackPanel.ContextMenu="{DynamicResource MergedContextMenu}" />
    </DataTemplate>

    <DataTemplate x:Key="singleDocDisplayGrid">
        <StackPanel StackPanel.ContextMenu="{DynamicResource SingleContextMenu}" />
    </DataTemplate>

</UserControl.Resources>

The DataTemplate s are used within a DevExpress FlowLayoutControl

In my scenario, I have two items in my FlowLayoutControl . One using the template mergedDocDisplayGrid and the other using singleDocDisplayGrid

The data is displayed correctly in the template, and other functionality such as mouse activity and drag dropping have been implemented successfully

Showing the context menu on either of the items works, but if I subsequently attempt to show the context menu again on the other item I get the following exception:

Message - Add value to collection of type 'System.Windows.Controls.ItemCollection' threw an exception.

Inner - Element already has a logical parent. It must be detached from the old parent before it is attached to a new one.

Stack Trace
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.LoadDeferredContent(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings parentSettings, Uri baseUri)
   at System.Windows.ResourceDictionary.CreateObject(KeyRecord key)
   at System.Windows.ResourceDictionary.OnGettingValue(Object key, Object& value, Boolean& canCache)
   at System.Windows.ResourceDictionary.OnGettingValuePrivate(Object key, Object& value, Boolean& canCache)
   at System.Windows.ResourceDictionary.GetValueWithoutLock(Object key, Boolean& canCache)
   at System.Windows.ResourceDictionary.GetValue(Object key, Boolean& canCache)
   at System.Windows.DeferredResourceReference.GetValue(BaseValueSourceInternal valueSource)
   at System.Windows.DependencyObject.GetEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, RequestFlags requests)
   at System.Windows.DependencyObject.GetValueEntry(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, RequestFlags requests)
   at System.Windows.DependencyObject.GetValue(DependencyProperty dp)
   at System.Windows.Controls.ContextMenuService.GetContextMenu(DependencyObject element)
   at System.Windows.Controls.ContextMenuService.ContextMenuIsEnabled(DependencyObject o)
   at System.Windows.Controls.ContextMenuService.OnContextMenuOpening(Object sender, ContextMenuEventArgs e)
   at System.Windows.Controls.ContextMenuEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   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.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
   at System.Windows.Forms.NativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(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 Camps.PrintViewerWPF.App.Main() in C:\Dev\Camps.Printing2\trunk\Camps.Printing2\Presentation\Camps.PrintViewerWPF\obj\x86\Release\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.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

The inner exception is self explanatory, and I am sure that I would be able to fix the issue in the code behind, however I feel there must be away to do this correctly in XAML as the re-use of the menu items is important to me

Any help would be greatly appreciated! Thanks

Try StaticResourceExtension and x:Shared="false" .

<MenuItem x:Key="PrintDoc" 
          x:Shared="false"              
          Header="Print" 
          Click="PrintDoc_OnClick"
          Icon="{StaticResource IconPrinter}" />

<ContextMenu x:Key="MergedContextMenu">
    <StaticResourceExtension ResourceKey="PrintDoc" />
</ContextMenu>

Check this link .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM