如何有效地设置StaticResourceExtension的数据上下文?

本文关键字:数据 上下文 StaticResourceExtension 有效地 设置 | 更新日期: 2023-09-27 18:18:29

我正在努力减少代码重复。考虑以下内容:

<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"传递给第二个commonItem实例?

我意识到在上面的例子中应该有更好的方法来做到这一点,这是XAML中真正发生的事情的一个非常精简的版本。

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

如何有效地设置StaticResourceExtension的数据上下文?

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

你可以在你的资源中保留一个菜单项的Style,与大多数菜单项共同的所有设置,并将该样式应用于你的项目。提示:如果你从Style中省略x:Key,只给它一个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>

所以在做了一些研究之后,我意识到我的设计太复杂了。以下是我所做的:

添加自定义菜单项类型:

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派生类型。