Reputation: 2135
I am trying to reduce code duplication. Consider the following:
<page...>
<page.resources>
<MenuItem x:Key="commonItem" />
</page.resources>
<TextBlock>
<TextBlock.ContextMenu>
<ContextMenu>
<ContextMenu.Resources>
<local:thingOne x:Key="one"/>
<local:thingTwo x:Key="two"/>
</ContextMenu.Resources>
<StaticResourceExtension PropertyKey="commonItem"/>
<StaticResourceExtension PropertyKey="commonItem"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</page>
How do I pass "one" to the first commonItem instance and "two" to the second?
I realize given the above example there would be a better way to do this, this is an extremely trimmed down version of what is really going on in our XAML.
More generally the question is, how do I follow good DRY principles when I have context menus all over the app that are different, but share some similar menu items?
Upvotes: 0
Views: 151
Reputation: 2135
So after some research, I realized I was trying to be too complicated. Here is what I did:
Add a custom menu item type:
public class MyMenuItem : MenuItem {}
And in the proper scope context (for me it was global):
<Style TargetType="namespace:MyMenuItem">
<!-- common control internals -->
</Style>
When it is needed to be used:
<ContextMenu>
<ContextMenu.Resources>
<local:thingOne x:Key="one"/>
<local:thingTwo x:Key="two"/>
</ContextMenu.Resources>
<namespace:MyMenuItem DataContext={Binding one}/>
<namespace:MyMenuItem DataContext={Binding two}/>
</ContextMenu>
This approach allows setting the DataContext and allows for automatic style application when combined with other MenuItems in a MenuBase control that need to have a different behavior.
One would expect a named style could be applied and a simple menu item could be used. I tried that and it did not work. I expect somewhere along the way something was overriding this for a MenuItem, but does not for a MenuItem derived type.
Upvotes: 0
Reputation: 13017
First, you shouldn't put a MenuItem
in your Resources
. This will just create a single instance of a MenuItem, and because it's a UIElement
it can only be used in one location on your Page.
You could instead keep a Style
for a MenuItem in your resources, with all setting that are common to most MenuItems, and apply that style to your items. Tip: If you omit the x:Key
from your Style
and just give it a TargetType
, it will be applied to all MenuItems
:
<Page...>
<Page.resources>
<Style TargetType="MenuItem" >
<Setter Property="Header" Value="{Binding}" />
<Setter Property="Foreground" Value="Lime" />
</Style>
</Page.resources>
<TextBlock>
<TextBlock.ContextMenu>
<ContextMenu>
<ContextMenu.Resources>
<local:thingOne x:Key="one"/>
<local:thingTwo x:Key="two"/>
</ContextMenu.Resources>
<MenuItem DataContext="{StaticResource one}" />
<MenuItem DataContext="{StaticResource two}" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</Page>
Upvotes: 1