闲话WPF之十六(WPF中的资源 [2])

在本系列的之十三中简单介绍了WPF中资源的资源。但是,没有给出任何具体的实例,在这个Post中将给出一个动态资源的例子,也算是响应daxian110的请求。并适当的扩展在前一个Post当中没有涉及的知识。

我们先看一个例子程序:

<Window x:Class="WindowsApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WindowsApplication1" Height="150" Width="100" Loaded="OnLoaded"
    >
    <Canvas>
      <Button Click="OnClick" Canvas.Left="10" Canvas.Top="20"
              Width="80" Height="30" Content="{DynamicResource TestRes1}"/>
      <Button Canvas.Left="10" Canvas.Top="60" Width="80"
              Height="30" Content="{DynamicResource TestRes2}"/>
    </Canvas>
</Window>

程序很简单,在窗口中添加了两个按钮,我们需要关注的是其中对Content属性。这个属性的作用就是设置按钮的内容。为什么这里的名称不是Text,而是Content?如此命名的原因和WPF中控件一个非常重要的概念有关:WPF中几乎任何的控件(也就是Element)都可以作为一个容器存在。也就是说我们在Content属性中可以包含其它任何你想显示的内容。不止是字符串文本。这种抽象的处理使我们可以把所有的内容等同对待,减少了很多处理上的麻烦。在本例子中,Content属性被和一个TestRes1和TestRes2关联起来。这个TestRes到底是什么呢?这就是动态资源的名称。具体的内容在显示按钮的时候决定。

注意上面Window中的Loaded属性,通过它我们可以设置一个函数名称,它将Window加载完成后被调用。下面就看看如何用代码控制TestRes:

private void OnLoaded(object sender, RoutedEventArgs e)
{
      string szText1 = "Res Text1";
      this.Resources.Add("TestRes1", szText1);

      string szText2 = "Res Text2";
      this.Resources.Add("TestRes2", szText2);
}

OnLoaded是Window1类中的一个成员函数,在这个函数里,我们需要添加资源,因为我们的XAML中需要使用TestRes1和TestRes2,运行时如果找不到对应资源,程序将失败。

现在,我们调用Add方法添加资源。第一个参数是资源的名称,第二个参数是添加的资源对象。

程序的运行效果如图1:

                  
      图1                                                图2

接下来我们看看修改资源的方法。在上面XAML的第一个按钮的Click属性中我们指定了一个OnClick事件方法。它将在点击按钮时调用,现在我们通过这个事件来修改另一个按钮的Content资源:

private void OnClick(object sender, RoutedEventArgs e)
{
      string szText = "New Res Text";
      this.Resources.Remove("TestRes2");
      this.Resources.Add("TestRes2", szText);
}

OnLoaded实现同样的简单,先调用Remove方法删除已有的TestRes2资源,然后重新添加一个新的TestRes2资源对象。点击第一个按钮后,下面按钮的文本将自动修改为新的资源对象。运行效果如图2。 

XAML加载器在分析XAML文件时,发现StaticResource,将会在当前Element的资源中查找指定的Key,如果查找失败,将沿着逻辑树向上查找,直到Root元素。如果还没有找到资源,再查找Application下定义的资源。在Application中定义的资源适用于整个应用程序。类似于全局对象。注意:使用Static资源时,不能向前引用。即使偶尔程序运行成功,向前引用的效率将非常低,因为它需要查找所有的ResourceDictionay。对于这种情况,使用DynamicResource将更适合。

另一方面,XAML加载器发现DynamicResource时,将根据当前的属性设置创建一个表达式,直到运行过程中资源需要,才根据表达式从资源中查找相关内容进行计算,返回所需的对象。注意,DynamicResource的查找于StaticResource基本类似,除了在定义了Style和Template时,会多一个查找目标。具体的细节可参数MSDN。

posted @ 2006-12-30 21:00 Yiling Lai 阅读(2691) 评论(11)  编辑 收藏 所属分类: WPF

  回复  引用    
#1楼 2006-12-30 21:53 | ml80 [未注册用户]
谢谢分享!
  回复  引用  查看    
#2楼 [楼主]2006-12-30 22:16 | Yiling Lai      
@ml80

客户啦!
  回复  引用  查看    
#4楼 2006-12-31 10:09 | daxian110      
谢谢楼主的文章!
关于这两种资源的使用,我有一点疑问:是不是Static资源只能在.xaml文件中定义,Dynamic资源只能在.cs文件中定义?如果这样的话,使用Dynamic资源时.xaml文件和.cs文件的耦合比使用Static资源要大,真有一天这两种文件由美工和程序员分别编写时,程序运行的风险也大。个人愚见,还请望指教!
  回复  引用  查看    
#5楼 [楼主]2006-12-31 10:36 | Yiling Lai      
@daxian110

Dynamic资源可以在XAML文件中定义!注意的区别在于我们使用资源时所用的标记扩展是StaticResource还是DynamicResourcez。而且资源还可以定义在单独的文件中,这样方便实现应用程序的本地化
  回复  引用  查看    
#6楼 2006-12-31 11:50 | daxian110      
@Yiling Lai

在 闲话WPF之十三(WPF中的资源)这篇文章提到的例子中,我曾试过把其中使用资源时的StaticResource标示符改成DynamicResource,运行效果是一样,这是不是意味着:虽然程序看上去运行结果一样,但是内部使用资源的机制已发生变化?
  回复  引用  查看    
#7楼 [楼主]2006-12-31 12:06 | Yiling Lai      
@daxian110

对的,运行效果一样,但是加载方式已经不同了!使用的机制也变了,正如我在这个Post最后所说的那样!
  回复  引用  查看    
#8楼 2006-12-31 13:07 | daxian110      
@Yiling Lai

非常感谢!
  回复  引用    
#9楼 2007-11-07 21:19 | 丰心 [未注册用户]
多谢楼主了,找到这种资料太高兴了,现在网上这wpf的资料太少了。非常感谢。
  回复  引用  查看    
#10楼 2008-05-22 01:58 | 水言木      
同样非常感谢楼主的文章,虽然我是在您发表了两年之后才看到它

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  博客园首页

  新闻频道

  社区

  小组

  博问

  网摘

  闪存

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-12-30 21:02 编辑过


相关链接: