首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Application.Resources与Window.Resources的隐式风格?

Application.Resources与Window.Resources的隐式风格?
EN

Stack Overflow用户
提问于 2012-01-27 15:38:22
回答 5查看 9.8K关注 0票数 37

我在查看这个问题时注意到,在Application.Resources中放置隐式TextBlock样式将该样式应用于所有TextBlocks,甚至包括其他控件(如ButtonsComboBoxes等)中的样式。

代码语言:javascript
复制
<Application.Resources>
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Blue" />
    </Style>
</Application.Resources>

将隐式样式放置在Window.Resources 不交叉控制模板边界。中,这样ButtonsComboBoxes之类的东西就可以维护其默认的黑色文本。

代码语言:javascript
复制
<Window.Resources>
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Blue" />
    </Style>
</Window.Resources>

此外,在Application.Resources中添加默认样式使其不能用另一个隐式样式覆盖该样式。

代码语言:javascript
复制
<!-- Doesn't work if implicit style with same property is in Application.Resources -->
<ComboBox.Resources>
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Red" />
    </Style>
</ComboBox.Resources>

我的问题是:

  • 为什么会这样呢?
  • Application.ResourcesWindows.Resources还有其他区别吗?
  • 什么时候应该用一种而另一种? 我理解Application.Resources应用于整个应用程序,而Window.Resources只应用于窗口,但我想知道为什么Application中的样式与Window中的样式不同
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-02-06 20:41:14

这实际上是添加到WPF中的唯一特殊处理,它是通过设计完成的。在FrameworkElement中可以在FindImplicitStyleResource方法中找到实现它的代码,该方法有效地执行:

代码语言:javascript
复制
internal static object FindImplicitStyleResource(FrameworkElement fe, object resourceKey, out object source)
{
        // ...
        DependencyObject boundaryElement = null;
        if (!(fe is Control))
            boundaryElement = fe.TemplatedParent;
        // ...
}

因此,经验法则是,隐式样式总是应用于控件(即从Control派生)。假设可以找到隐式样式。

对于ControlTemplate中使用的不从Control派生的元素(如TextBlock ),隐式样式查找将不会跨越它的模板父元素。在上面的例子中,这将是ComboBox

我相信这样做是为了使TextBlock的非应用隐式样式不会无意中应用于控制模板中使用的TextBlock元素,开发人员可能知道也可能不知道。隐式样式只应用于开发人员在自己的XAML中实际创建的TextBlocks。

应用程序隐式样式仍然允许全局样式,例如增加字体大小。但可能造成的混乱比它的价值更多。

没有很好的答案来说明何时使用其中一种与另一种,因为它们各有其功能。显然,如果不想影响应用程序中的每个TextBlock,就不应该将样式放在应用程序资源中。

但请记住,这会影响任何非Control元素,如Shape元素。

票数 29
EN

Stack Overflow用户

发布于 2012-01-27 16:03:52

很简单很简单

如果希望在整个应用程序之间共享资源,可以使用Application.Resources

如果希望在整个窗口之间共享资源,可以使用Window.Resources

如果希望在单个控件之间共享资源,可以使用(任何控件).Resources

假设您有多个窗口,但您只想在一个窗口中使用默认样式,而不是另一个窗口,那么您将使用Windoe.Resources。

票数 2
EN

Stack Overflow用户

发布于 2012-02-04 06:03:31

瑞秋,我不认为“风格”有什么特别之处。此外,不存在“跨越模板边界”的问题。其原因是不同的,它去不同的“树”在一个WPF应用程序。通过你的问题,我发现你描绘的是一个具有以下等级的世界:

  • 控件中的应用程序=>窗口=>控件=>元素

没有这样的等级制度。WPF应用程序中有不同的树,其中最著名的是逻辑树和视觉树,但是有更多的树(路由事件树和资源查找树,语义略有不同)。

假设以下XAML:

代码语言:javascript
复制
<Window x:Class="SO.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button x:Name="btn" Click="click">Click Me</Button>
    </Grid>
</Window>

对于这个XAML,逻辑树如下所示:

  • 窗口=>网格=>按钮=>字符串

按钮中的textblock不是逻辑树的一部分(不过它是VisualTree的一部分)。

通过LogicalTree查找资源,有一个不同之处。在到达顶层对象后,查找资源算法将按此顺序查看应用程序资源字典,然后查看主题资源字典,然后查看系统资源字典。

见下列条款:

  • 关于树木:http://msdn.microsoft.com/en-us/library/ms753391.aspx
  • 关于查找资源:http://msdn.microsoft.com/en-us/library/ms750613.aspx#staticdynamic,并查找“动态资源查找行为”部分

最后,为了证明我的观点,将以下资源添加到应用程序XAML中:

代码语言:javascript
复制
<Application x:Class="SO.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:clr="clr-namespace:System;assembly=mscorlib"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
        <clr:String x:Key="MyResource">Hello Application Resource</clr:String>
    </Application.Resources>
</Application>

以及下面的代码:

代码语言:javascript
复制
private void click(object sender, RoutedEventArgs e)
{
    // Logical Children of btn
    Debug.WriteLine("Children of btn:");
    foreach( var x in LogicalTreeHelper.GetChildren(btn) ) {
        Debug.WriteLine("{0} : {1}", x, x.GetType());
    }

    // Walk the visual tree
    Debug.WriteLine("The Visual Tree:");
    WalkVisual(0, this);

    // Find the textblock within the button
    DependencyObject p = btn;
    while (p.GetType() != typeof(TextBlock))
        p = VisualTreeHelper.GetChild(p, 0);
     TextBlock tb = p as TextBlock;

    // Now climp the textblock through the logical tree
    while (p != null)
    {
        Debug.WriteLine("{0}", p.GetType());
        p = LogicalTreeHelper.GetParent(p);
    }

    // Find a resource for the textbox
    string s = tb.FindResource("MyResource") as string;
    Debug.WriteLine("MyResource Content: {0}", s);
}

private void WalkVisual(int indent, DependencyObject p)
{
    string fmt = string.Format("{{0,{0}}}{{1}}", indent * 4);
    Debug.WriteLine(fmt, "", p.GetType());
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(p); ++i)
    {
        WalkVisual(indent+1,VisualTreeHelper.GetChild(p, i));
    }
}

所以..。一旦你理解了第一个问题(‘为什么是那个’),其他的问题就会分崩离析。应用程序资源和窗口资源的不同之处在于,应用程序资源可以由应用程序中的任何DependencyObject创建,包括在其他程序集中定义的资源。当这是你想要的时候,你就会使用它:-)

u。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9035878

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档