silverlight   发布时间:2022-05-04  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Silverlight 里如何实现隐式样式大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

  Silverlight 里如何实现隐式样式,ImplicitStyleManager 的实现思想 在 WPF 中,我们可以方便的在全局范围定义一个样式,就可以应用到所有这种类型的对象,这就是所谓的隐式样式(implicit StylE),比如: < Window  x:Class ="WpfImplicitStyle.Window1"     xmlns ="http://scheR_936_11845@as.mi
 

Silverlight 里如何实现隐式样式,ImplicitStyleManager 的实现思想

在 WPF 中,我们可以方便的在全局范围定义一个样式,就可以应用到所有这种类型的对象,这就是所谓的隐式样式(implicit StylE),比如:

< Window  x:Class ="WpfImplicitStyle.Window1"
    xmlns
="http://scheR_936_11845@as.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
="http://scheR_936_11845@as.microsoft.com/winfx/2006/xaml"
    title
="Window1"  Height ="300"  Width ="300" >
    
< Grid >
        
< Grid.resources >
            
<!--  针对一种类型设置全局样式  -->
            
< Style  TargetType ="Button" >
                
< Setter  Property ="BACkground"  Value ="AliceBlue"   />  
            
</ Style >
        
</ Grid.resources >
        
< StackPanel >
            
< Button > Button a </ Button >
            
< Button > Button b </ Button >
        
</ StackPanel >
    
</ Grid >
</ Window >


这样之后,两个按钮就都变成了浅蓝色的背景。

但是在 Silverlight 里没有办法这样做。我们必须手工对每一个需要设置样式的控件添加 Style="{Staticresource someStylE}" 这样的语句,挨个设置,非常麻烦。

好在 Silverlight Toolkit 里提供了一个类似的实现,叫做 ImplicitStyleManager (隐式样式管理器,可以简称 ISM)。

该类的使用方法,是在某个根元素上设置一个附加属性(Attached Property),然后,该元素下属的视觉树里符合特定类型的子元素的样式,就可以被自动应用隐式样式了。
例子如下:

< UserControl  x:Class ="ImplicitStyleTest.Page"
    xmlns
="http://scheR_936_11845@as.microsoft.com/winfx/2006/xaml/presentation"  
    xmlns:x
="http://scheR_936_11845@as.microsoft.com/winfx/2006/xaml"  
    Width
="400"  Height ="300"
        xmlns:theming
="clr-namespace:Microsoft.Windows.Controls.Theming;assembly=Microsoft.Windows.Controls.Theming" >
    
< Grid  x:Name ="LayoutRoot"  BACkground ="White" >
        
< Grid.resources >
            
< Style  TargetType ="Button" >
                
< Setter  Property ="BACkground"  Value ="AliceBlue"   />
            
</ Style >
        
</ Grid.resources >
        
<!--  在根元素上设置一次就可以了  -->
        
< StackPanel  theming:ImplicitStyleManager.Applymode ="Auto" >
            
< Button  Content ="Button a" ></ Button >
            
< Button  Content ="Button b" ></ Button >
        
</ StackPanel >
    
</ Grid >
</ UserControl >

运行一下例子试试@R_81_10585@,两个按钮的样式都被设置了,这样就实现了类似 WPF 里的隐式样式行为。

在这个例子里可以看到,Applymode 属性被设置成了 Auto. 其实它一共有3个可选值,分别代表如下含义:

1. Auto@H_641_403@
每当 layout updated 的时候,ISM 会重新应用隐式样式。在这种模式下如果元素在以后被动态的加入到视觉树中,它们将被应用隐式样式。
需 要注意的是,Layoutupdated 事件发生的非常频繁,并且不光是当你添加元素后才发生。而我们又没有类似 ItemAddedToTree 的事件,如果视觉树比较大的话,ISM 遍历它的时候就会花费比较多的时间,这可能给性能带来一定的影响。但是为了方便,这里只好做一些折中的权衡,牺牲一点性能。如果视觉树很大的时候,可以 虑改用 OneTime 模式。

2. OneTime
@H_641_403@仅在第一次加载时起作用,对后面动态加到 visual tree 里的元素不起作用。
有 时候,你的视觉树很大,所以你不虑用 Auto 模式。这时候你可以用 OneTime 模式一次性应用样式;同时,需要在添加新节点之后,在代码里手工调用 ISM 的 Apply 方法,这样可以重新应用一次样式。这样的办法可以避免 Auto 模式的一些性能损失。

3. None@H_641_403@
效果跟没设置 Applymode 属性一样。

了解了 ISM 如何使用,我们来看看它是怎么实现的。

我们知道,Silverlight 元素里面的 Style 在运行时只能被设置一次,否则就会出错,ISM 也不例外,也要受这个制约。

ISM 的实现原理大致如下:@H_641_403@

1. 定义一个叫做 Applymode 的附加属性(Attached Property),提供给需要设置样式的“根”元素使用。
而我 们知道,附加属性可以在 xaml 里被设置,这就像上面的例子里所写的那样;同时,它有一个最大的好处,就是可以定义属性改变时触发的回调函数注册时定义在 PropertyMetadata 里面)。这样,当我们在代码里设置了 Applymode 后,ISM 就能触发这个回调函数进行处理了。

2. 在这个回调函数中,注册元素的 Layoutupdated 事件处理函数,这样,在该元素不管因为什么原因更新其 layout 的时候,就能够得到通知
这里最巧妙的地方是:将元素 Layoutupdated 事件的处理委托以依赖属性(DependencyProperty) 的形式存在该元素自身的属性中,这样就省去了自行管理很多 event handler 的烦恼了。。。依赖属性真的是个好东西啊!
代码

///   <sumMary>
///  ApplymodeProperty property changed handler.
///   </sumMary>
///   <param NAME="dependencyObject"> FrameworkElement that changed its 
///  Applymode. </param>
///   <param NAME="eventArgs"> Event arguments. </param>
private   static   void  OnApplymodePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
{
    FrameworkElement element 
=  dependencyObject  as  FrameworkElement;
    
if  (element  ==   null )
    {
        
throw   new  argumentNullException( " dependencyObject " );
    }

    ImplicitStylesApplymode oldMode 
=  (ImplicitStylesApplymodE)eventArgs.OldValue;
    ImplicitStylesApplymode newMode 
=  (ImplicitStylesApplymodE)eventArgs.NewValue;

    ImplicitStyleManager.SetHasBeenStyled(element, 
false );

    EventHandler eventHandler 
=  ImplicitStyleManager.GetLayoutupdatedHandler(element);

    
//  If element is automatically styled (once or always) attach event 
    
//  handler.
     if  ((newMode  ==  ImplicitStylesApplymode.Auto  ||  newMode  ==  ImplicitStylesApplymode.oneTimE)
        
&&  oldMode  ==  ImplicitStylesApplymode.NonE)
    {
        
if  (eventHandler  ==   null )
        {
            eventHandler 
=
                (sender, args) 
=>
                {
                    ImplicitStyleManager.PropagateStyles(element, 
false );
                };

            ImplicitStyleManager.SetLayoutupdatedHandler(element, eventHandler);
            element.Layoutupdated 
+=  eventHandler;
        }
    }
    
else   if  ((oldMode  ==  ImplicitStylesApplymode.Auto  ||  oldMode  ==  ImplicitStylesApplymode.oneTimE)
        
&&  newMode  ==  ImplicitStylesApplymode.NonE)
    {
        
if  (eventHandler  !=   null )
        {
            element.Layoutupdated 
-=  eventHandler;
            ImplicitStyleManager.SetLayoutupdatedHandler(element, 
null );
        }
    }
}

3. 在上述 Layoutupdated 的事件处理函数中,遍历控件的视觉树,对符合条件的元素设置 Style(也只能设置一次)。
这里值得一说的是遍历树的代码技巧,为了避免递归或者类似方法遍历树造成的开销,这里实际使用了一种很巧妙的 Stack 来访问树节点。并且,在所有需要遍历的地方,尽可能的使用了 yield return,以一种函数式编程的写法来延迟实际对节点的操作。

具体代码不细细解释了,这里把 MS 的代码贴来仅供欣赏一下 Functional ProgrAMMing,有兴趣的朋友可以自己研究:

///   <sumMary>
///  This method propagates the styles in the resources associated with
///  a framework element to its descendents. This results in a  
///  style inheritance that mimics WPF's behavior.
///   </sumMary>
///   <param NAME="element"> the Element that will have its styles 
///  propagated to its children. </param>
///   <param NAME="recurse"> Whether to recurse over styled elements that
///  are set to OneTime and have already been styled. </param>
private   static   void  PropagateStyles(FrameworkElement element,  bool  recursE)
{
    BaseMergedStyleDictionary initialDictionary 
=  GetMergedStyleDictionary(element);

    
//  Create stream of elements and their base MERGEd style 
    
//  Dictionaries by traversing the logical tree.
    IEnumerable < Tuple < FrameworkElement, BaseMergedStyleDictionary >>  elementsToStyleAndDictionaries  =
       @R_762_3816@alProgrAMMing.Traverse(
            
new  Tuple < FrameworkElement, BaseMergedStyleDictionary > (element, initialDictionary),
            (elementAndDictionary) 
=>  
                elementAndDictionary
                    .First
                    .GetLogicalChildrenDepthFirst()
                    .SELEct(childElement 
=>  
                        
new  Tuple < FrameworkElement, BaseMergedStyleDictionary > (
                            childElement, 
                            
new  MERGEdStyleresourceDictionary(
                                ImplicitStyleManager.GetExternalresourceDictionary(childElement) 
??  childElement.resources,
                                elementAndDictionary.Second))),
            (elementAndDictionary) 
=>  recurs ||
                (ImplicitStyleManager.GetApplymode(elementAndDictionary.First) 
!=  ImplicitStylesApplymode.oneTime  ||
                
! ImplicitStyleManager.GetHasBeenStyled(elementAndDictionary.First)));

    
foreach  (Tuple < FrameworkElement, BaseMergedStyleDictionary >  elementToStyleAndDictionary  in  elementsToStyleAndDictionaries)
    {
        FrameworkElement elementToStyle 
=  elementToStyleAndDictionary.First;
        BaseMergedStyleDictionary styleDictionary 
=  elementToStyleAndDictionary.Second;

        
bool  styleApplied  =   false ;

        
if  (elementToStyle.Style  ==   null )
        {
            Style style 
=  styleDictionarY[GetStyleKey(elementToStylE)];
            
if  (style  !=   null )
            {
                elementToStyle.Style 
=  style;
                styleApplied 
=   true ;
            }
        }

        
if  (ImplicitStyleManager.GetApplymode(elementToStylE)  ==  ImplicitStylesApplymode.oneTime  &&  (VisualTreeHelper.GetChildrenCount(elementToStylE)  >   @H_673_1030@0   ||  styleApplied))
        {
            ImplicitStyleManager.SetHasBeenStyled(elementToStyle, 
true );
        }
    }
}

 



http://www.beacosta.com/blog/?p=54
http://www.beacosta.com/blog/?p=55
(好像是 MS Silverlight 团队的一个美女,推荐订阅或关注她的博客

 

原文:http://www.cnblogs.com/RChen/archive/2008/12/16/1355906.html

大佬总结

以上是大佬教程为你收集整理的Silverlight 里如何实现隐式样式全部内容,希望文章能够帮你解决Silverlight 里如何实现隐式样式所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。