【问题标题】:How do I effectively set the DataContext of a StaticResourceExtension如何有效地设置 StaticResourceExtension 的 DataContext
【发布时间】:2013-06-15 20:30:36
【问题描述】:

我正在尝试减少代码重复。考虑以下几点:

<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 原则?

【问题讨论】:

    标签: c# wpf xaml datacontext


    【解决方案1】:

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

    您可以改为在资源中为 MenuItem 保留 Style,使用大多数 MenuItem 通用的所有设置,并将该样式应用于您的项目。提示:如果您从 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>
    

    【讨论】:

    • 您可以通过在资源的菜单项声明中添加 x:Shared="False" 来解决您引用的第一个问题。我不能“轻松”地使用一种风格。我目前正在将此作为自定义控件,但进展不顺利。
    【解决方案2】:

    所以经过一些研究,我意识到我试图变得过于复杂。这是我所做的:

    添加自定义菜单项类型:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-19
      • 2016-02-06
      • 1970-01-01
      • 2023-03-22
      • 2013-12-26
      • 2014-02-27
      • 1970-01-01
      相关资源
      最近更新 更多