UWP基础教程 - XAML资源

在Windows 10 UWP应用开发中,XAML用于应用界面设计,无论是开发人员还是设计人员经常会设计自定义用户界面或者控件行为,其中会涉及到不同方面的代码设计,例如控件模板控件样式动画设计等。为了方便设计,管理和重复利用这些通用代码,XAML提出了资源(Resources)的概念   资源(Resources),其概念和Web应用中的CSS(Cascading Style Sheets)样式类似,其目的为了实现对象的重复调用。在Windows 10 UWP应用开发中,资源的概念不仅仅局限于对控件样式的定义,而且还包括对控件模板的定义,对字体的控制等。在实际项目中,开发人员可以在资源中设置多种不同控件属性,在多个页面调用通用资源代码,这样不仅有助于代码复用,也能够提高应用维护的一致性。

我们来看一下定义一个资源的语法格式:

<根元素对象.Resources>
     <资源定义 />
</根元素对象.Resources>

在Windows 10 UWP应用开发中,每个Framework对象都支持Resources属性,也就是说,可以在不同控件或者页面定义特定的Resources, 在Page,Grid,Button定义Resources都是可以的。

XAML资源的概念在一定程度上简化了XAML页面代码,对于管理批量资源代码集合,XAML还提供资源字典标记进行声明。 在Windows 10 UWP应用开发中,所有能够被定义在资源字典(ResourceDictionary)的对象必须是可被共享使用的。可以被应用于资源字典的对象如下:

  1. Style 和 Template
  2. Brushes 和 Colors
  3. Animation types (Storyboard)
  4. Transforms
  5. Matrix 和 Maxtrix3D 
  6. Point 
  7. Thickness 和 CornerRadius
  8. XAML intrinsic data types

在资源字典(ResourceDictionary)中,每一个资源项必须定义x:Key,也就是所谓的唯一标识的资源名称,这样可以方便读取访问。例如以下代码,在Page.Resources中定义资源x:Key = "bg", 我们可以在Button中调用资源x:Key,应用资源到控件。

<Page>
    <Page.Resources>
            <LinearGradientBrush x:Key="bg" StartPoint="0.5,0" EndPoint="0.5,1">
                <GradientStop Color="Yellow" Offset="0.0" />
                <GradientStop Color="Blue" Offset="0.5" />
                <GradientStop Color="Green" Offset="1.0" />
            </LinearGradientBrush>
    </Page.Resources>
    <Button Background = "{StaticResource bg}"/>
</Page>

所有的XAML代码都可以转化为C#代码的,那么我们来看看上面XAML的C#实现。

ResourceDictionary dict = new ResourceDictionary();
LinearGradientBrush bgBrush = new LinearGradientBrush();
bgBrush.StartPoint = new Point(0.5,0);
bgBrush.EndPoint = new Point(0.5,1);
GradientStopCollection stops = new GradientStopCollection();
GradientStop stop1 = new GradientStop();
stop1.Color = Colors.Yellow;
            stop1.Offset = 0.0;
            stops.Add(stop1);
            GradientStop stop2 = new GradientStop();
stop2.Color = Colors.Blue;
            stop2.Offset = 0.5;
            stops.Add(stop2);
            GradientStop stop3 = new GradientStop();
stop3.Color = Colors.Green;
            stop3.Offset = 1.0;
            stops.Add(stop3);
            bgBrush.GradientStops = stops;
            dict.Add("bg", bgBrush);
this.LayoutRoot.Resources = dict;
this.btn.Background = (LinearGradientBrush)this.LayoutRoot.Resources["bg"];

Resources分为两类FrameworkElement.ResourcesApplication.Resources

  1. FrameworkElement.Resources是将资源对象应用于同一个对象树的不同对象上,也可被称为即时资源(Immediate Resources), 或者称为页面资源(Page Resources)。通常来说,FrameworkElement.Resources会被定义在XAML页面根元素上。  
  2. Application.Resources可以被认为是贯串整个应用级别的资源,资源被定义在Application.Resources中,相比 FrameworkElement.Resources而言,Application.Resources应用范围较广,其生命周期也比 FrameworkElement.Resources要长。通常来说Application.Resources是被定义在启动就加载的全局容器里,例如App.xaml。

我们先来看下FrameworkElement.Resources的使用,如下在Page中定义Resources

<Page>
    <Page.Resources></Page.Resources>
</Page>

Application.Resources定义是在Application.Resources中,如下代码所示

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

为了方便调用外部资源文件,资源字典(ResourceDictionary)提供了MergedDictionaries属性。 通常来说,合并资源字典属性会被定义在Application.Resources, 也就是在App.xaml文件中。 在使用合并资源字典属性时,需要注意资源的查找顺序,例如:

<Application.Resources>
    <ResourceDictionary>
      <SolidColorBrush Color="red" x:Key="muddyBrush"/>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="test1.xaml" />
        <ResourceDictionary Source="test2.xaml" />
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources> 
![image.png](./10)

在上面代码的ResourceDictionary.MergedDictionaries中定义多个外部资源文件,其查找资源顺序是从下往上逆序查找的。test1.xaml和test2.xaml。 如果在两个资源文件中存在相同x:key的资源,test2.xaml中的资源将被优先采用。

作为外部资源合并,应用本身定义的资源永远具有较高的优先级,也就是说,如果在本地资源定义中,出现与test1.xaml,test2.xaml同名的资源,本地资源都被会优先采用。

在UWP中,主题资源字典(ThemeDictionaries)是一个特殊的合并资源字典。

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <x:String x:Key="BackButtonGlyph"></x:String>
        <x:String x:Key="BackButtonSnappedGlyph"></x:String>
    </ResourceDictionary>

    <ResourceDictionary x:Key="HighContrast">
        <x:String x:Key="BackButtonGlyph"></x:String>
        <x:String x:Key="BackButtonSnappedGlyph"></x:String>
    </ResourceDictionary>
    <ResourceDictionary x:Key="GreenTheme">
        <SolidColorBrush x:Key="MyBackgroundBrush" Color="Green"></SolidColorBrush>
    </ResourceDictionary>

    <ResourceDictionary x:Key="BlackTheme">
        <SolidColorBrush x:Key="MyBackgroundBrush" Color="Black"></SolidColorBrush>
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

与MergedDictionaries属性相比较,在使用ThemeDictionaries时,需要为每个资源定义一个x:Key.例如上面的代码中的Default, HighContrast,在不同的主题时会查找不同主题的资源进行渲染。

关于UWP开发XAML的部分到此就告一段落了,有什么问题欢迎留言讨论。

Comment