样式,模板和ResourceDictionaries

时间:2016-03-01 22:30:18

标签: c# wpf templates styles resourcedictionary

我已经做了一段时间的WPF项目了,但是我在很大程度上远离了模板和资源字典,因为它们是一个集群#。为了进入下一个级别,我已经做了很多谷歌搜索试图找到使用资源词典等应用样式的最佳实践,但似乎最好的做法是基于习惯和偏好。我遇到的大多数例子都假设你已经知道所有事情或者没有包括所有不同的情况。最糟糕的是,有一些已知的错误和情况会影响性能,但了解这些问题是什么并纠正它们本身就是另一个麻烦。

抱歉咆哮。以下是我需要解决的问题:

假设我有一个默认的rd(资源字典),其中包含针对文本块,按钮,文本框等的样式。然后,我有另一个类似的资源字典,适用于像Expander(或TabItem)这样的集合相同的控件(按钮,文本框,......)。

  1. 可以进行那种设置吗?

  2. 如何覆盖位于特定扩展器内的控件的默认rd?我已经尝试在扩展器的资源中添加对资源字典的引用;但是,默认的rd似乎会覆盖该样式。

  3. 模板的用途是什么,何时使用?

  4. 这是我目前的设置:

    的App.xaml:

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources/rdMainStyle.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
    

    rdMainStyle.xaml:

    <Style x:Key="baseStyle" TargetType="FrameworkElement">
        <Setter Property="Width" Value="Auto"/>
        <Setter Property="Height" Value="Auto"/>
        <Setter Property="MinWidth" Value="70pt"/>
    </Style>
    
    <Style TargetType="{x:Type Button}" BasedOn="{StaticResource baseStyle}">
        <Setter Property="Margin" Value="5, 0, 0, 5"/>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
    </Style>
    <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource baseStyle}">
        <Setter Property="MinWidth" Value="65pt"/>
        <Setter Property="Margin" Value="5, 0, 0, 5"/>
    </Style>
    

    rdExpanderStyle.xaml:

    <Style x:Key="expanderBaseStyle" TargetType="FrameworkElement">
        <Setter Property="Height" Value="Auto"/>
        <Setter Property="Margin" Value="5, 0, 0, 5"/>
    </Style>
    
    <Style TargetType="{x:Type Button}" BasedOn="{StaticResource expanderBaseStyle}">
        <Setter Property="Width" Value="70pt"/>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
    </Style>
    <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource expanderBaseStyle}">
        <Setter Property="Width" Value="65pt"/>
    </Style>
    

    在主窗口内:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    
        <Expander Grid.Row="0" Name="expSync" Header="More Options">
            <Expander.Resources>
                <ResourceDictionary Source="Resources/rdExpanderStyle.xaml" />
            </Expander.Resources>
        </Expander>
        <StackPanel Margin="0,5,0,0">
            <TextBlock Text="bluh"/>
            <Button  Content="Test"  />
        </StackPanel>
    </Grid>
    

1 个答案:

答案 0 :(得分:1)

  
      
  1. 可以进行那种设置吗?
  2.   

是的,没关系。事实上,造型/模板/主题/等。在WPF中都是关于这种层次结构的。即能够在一个地方定义默认值,然后用一个优先级更高的新定义覆盖它。

  
      
  1. 如何覆盖位于特定扩展器内的控件的默认rd?我尝试在扩展器资源中添加对资源字典的引用;但是,默认的rd似乎会覆盖该样式。
  2.   

问题与Expander.Header属性的内容是简单的string有关。这将映射到ContentPresenter类的自定义样式(本身是Expander类的自定义样式的一部分),因此当您尝试使用本地声明的样式设置样式时,将忽略该样式。您稍后尝试覆盖样式实际上在样式层次结构中太过分了。全局样式有效,因为该样式的应用早于用于控件的自定义样式。

您可以通过为Expander控件的内容提供更明确的定义来解决此问题。例如:

<Expander Grid.Row="0" Name="expSync">
  <Expander.Resources>
    <ResourceDictionary Source="Resources/rdExpanderStyle.xaml" />
  </Expander.Resources>
  <Expander.Header>
    <TextBlock Text="More Options"/>
  </Expander.Header>
</Expander>

通过明确提供TextBlock作为内容,您可以使用从<{1}}文件导入的样式之后来的控件实例,它们将是根据需要使用。

  
      
  1. 模板的目的是什么?何时使用模板?
  2.   

对此的全面讨论将超出合理的Stack Overflow答案的范围。 MSDN,Stack Overflow以及其他地方有很多资源可用于描述如何在WPF中使用模板。那说......

模板的目的是为实例化控件提供一种模式。在某些情况下,您要声明特定控件的模板,在其他情况下,您要声明模型以及#34;视图模型&#34;数据类型。前一种情况是关于定制现有控件类型的外观和行为;后一种情况是以抽象,分离,可重用的方式将业务逻辑数据结构映射到视觉外观。

你什么时候使用它们?好吧,我会说目的回答了这个问题。如果您需要自定义可模板化控件,则可以使用模板来执行此操作。如果需要将视图模型对象呈现为控件的组合,则可以使用模板来执行此操作(例如,当您的视图模型表示rdExpanderStyle.xaml中的项目时)。我会说视图模型场景比通过模板定制控件更普遍,但这不是基于确凿的证据;这只是我对这种情况的一般认识。


最后,我提出一些建议,我的意思是没有冒犯:

虽然你的咆哮是可以理解的,但它没有效率,更多的是你自己的经验不足而不是WPF的实际质量。我知道,因为我自己也去过那里。是的,WPF很复杂,很难学。是的,它确实有许多行为不直接或明显的地方。

但是: a) WPF中模板和资源的状态甚至不是 close (用你的话说......我相信我有了预期的含义)&#34;群集#&#34; ;相反,这些是WPF的基本元素,如果设计非常复杂则具有逻辑性,并且在正确使用时工作得很好,而 b)实际上是合理的,客观的&#34;最佳实践&#34;处理样式和资源字典,在很大程度上基于支持OOP设计的同一种理念(即尽可能广泛地定义,在必要时专门化以避免基本定义中的特殊情况代码)。

(我应该在那里停下来,但主动提出的建议还附带一些不请自来的讲故事... :))

多年来,我发现自己对大量的API,平台等进行了咆哮。但是随着我年龄的增长,咆哮越来越少,我也越来越多了。被迫承认我的许多咆哮真的是关于我对我尚未完全理解的事情感到沮丧。是的,有例外......偶尔,我的一个咆哮仍然达到了公平的目标。但我大多发现,学习一个新的编程环境需要调整态度,寻求推动环境设计的思维模式,并重新训练自己遵循相同的模式,这样我才能看到环境设计师看到它的方式。

不要担心。你还有机会咆哮。在我的编程生涯早期,我只是吸取了教训,如果你的程序不能正常工作,那么当我找到程序时,它总是你的程序中的错误而不是操作系统中的错误我自己为一台实验计算机编写代码,这台计算机几乎每天都要求硬件工程师摆弄它以保持其正常运行。我花了几天的时间才学会接受这样一个想法,即我刚学到的非常重要的一课需要改为意味着&#34;它的几乎总是一个错误你的节目&#34;。那是几十年前,计算机从那时起变得更加复杂,因此编程环境有更多的机会而不是你自己的程序存在缺陷。

但不要忘记:对于编写代码应用程序方面的人而言,制作错误的人比编写系统方面的人更常见。如果不出意外,系统端代码会被更好地测试 lot ,只需被像你这样的大量人使用。 :)