如何有效地设置StaticResourceExtension的DataContext

时间:2013-06-15 20:30:36

标签: c# wpf xaml datacontext

我正在尝试减少代码重复。请考虑以下事项:

<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>

如何将“one”传递给第一个commonItem实例,将“two”传递给第二个?

我知道,鉴于上面的例子,有更好的方法可以做到这一点,这是我们的XAML中真正发生的一个非常精简的版本。

更普遍的问题是,当我在不同的应用程序中有上下文菜单但共享一些类似的菜单项时,如何遵循良好的DRY原则?

2 个答案:

答案 0 :(得分:1)

首先,您不应在MenuItem中添加Resources。这只会创建一个MenuItem的单个实例,因为它是UIElement,它只能在您的页面上的一个位置使用。

您可以为资源中的MenuItem保留Style,其中包含大多数MenuItem通用的所有设置,并将该样式应用于您的项目。提示:如果您忽略x:Key中的Style而只是给它TargetType,则会将其应用于所有 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>

答案 1 :(得分:0)

经过一番研究,我意识到自己太过复杂了。这是我做的:

添加自定义菜单项类型:

public class MyMenuItem : MenuItem {}

在适当的范围内容中(对我而言,它是全球性的):

<Style TargetType="namespace:MyMenuItem">
    <!-- common control internals -->
</Style>

需要使用时:

<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>

此方法允许设置DataContext,并允许在与需要具有不同行为的MenuBase控件中的其他MenuItem结合时自动样式应用。

可以预期可以应用命名样式,并且可以使用简单的菜单项。我试过了,但没用。我希望在某个地方有一些东西覆盖了MenuItem,但不适用于MenuItem派生类型。