大佬教程收集整理的这篇文章主要介绍了Silverlight 里如何实现隐式样式,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
在 WPF 中,我们可以方便的在全局范围定义一个样式,就可以应用到所有这种类型的对象,这就是所谓的隐式样式(implicit StylE),比如:
这样之后,两个按钮就都变成了浅蓝色的背景。
但是在 Silverlight 里没有办法这样做。我们必须手工对每一个需要设置样式的控件添加 Style="{Staticresource someStylE}" 这样的语句,挨个设置,非常麻烦。
好在 Silverlight Toolkit 里提供了一个类似的实现,叫做 ImplicitStyleManager (隐式样式管理器,可以简称 ISM)。
该类的使用方法,是在某个根元素上设置一个附加属性(Attached Property),然后,该元素下属的视觉树里符合特定类型的子元素的样式,就可以被自动应用隐式样式了。
例子如下:
运行一下例子试试@R_81_10585@,两个按钮的样式都被设置了,这样就实现了类似 WPF 里的隐式样式行为。
在这个例子里可以看到,Applymode 属性被设置成了 Auto. 其实它一共有3个可选值,分别代表如下含义:
1. Auto@H_641_403@
2. OneTime
3. None@H_641_403@
了解了 ISM 如何使用,我们来看看它是怎么实现的。 我们知道,Silverlight 元素里面的 Style 在运行时只能被设置一次,否则就会出错,ISM 也不例外,也要受这个制约。 ISM 的实现原理大致如下:@H_641_403@
1. 定义一个叫做 Applymode 的附加属性(Attached Property),提供给需要设置样式的“根”元素使用。 2. 在这个回调函数中,注册元素的 Layoutupdated 事件处理函数,这样,在该元素不管因为什么原因更新其 layout 的时候,就能够得到通知。 3. 在上述 Layoutupdated 的事件处理函数中,遍历控件的视觉树,对符合条件的元素设置 Style(也只能设置一次)。 具体代码不细细解释了,这里把 MS 的代码贴来仅供欣赏一下 Functional ProgrAMMing,有兴趣的朋友可以自己研究: 原文:http://www.cnblogs.com/RChen/archive/2008/12/16/1355906.html
每当 layout updated 的时候,ISM 会重新应用隐式样式。在这种模式下如果元素在以后被动态的加入到视觉树中,它们将被应用隐式样式。
需 要注意的是,Layoutupdated 事件发生的非常频繁,并且不光是当你添加元素后才发生。而我们又没有类似 ItemAddedToTree 的事件,如果视觉树比较大的话,ISM 遍历它的时候就会花费比较多的时间,这可能给性能带来一定的影响。但是为了方便,这里只好做一些折中的权衡,牺牲一点性能。如果视觉树很大的时候,可以考 虑改用 OneTime 模式。
@H_641_403@仅在第一次加载时起作用,对后面动态加到 visual tree 里的元素不起作用。
有 时候,你的视觉树很大,所以你不考虑用 Auto 模式。这时候你可以用 OneTime 模式一次性应用样式;同时,需要在添加新节点之后,在代码里手工调用 ISM 的 Apply 方法,这样可以重新应用一次样式。这样的办法可以避免 Auto 模式的一些性能损失。
效果跟没设置 Applymode 属性一样。
而我 们知道,附加属性可以在 xaml 里被设置,这就像上面的例子里所写的那样;同时,它有一个最大的好处,就是可以定义属性改变时触发的回调函数(注册时定义在 PropertyMetadata 里面)。这样,当我们在代码里设置了 Applymode 后,ISM 就能触发这个回调函数进行处理了。
这里最巧妙的地方是:将元素 Layoutupdated 事件的处理委托以依赖属性(DependencyProperty) 的形式存在该元素自身的属性中,这样就省去了自行管理很多 event handler 的烦恼了。。。依赖属性真的是个好东西啊!
代码:
///
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
);
}
}
}
这里值得一说的是遍历树的代码技巧,为了避免递归或者类似方法遍历树造成的开销,这里实际使用了一种很巧妙的 Stack 来访问树节点。并且,在所有需要遍历的地方,尽可能的使用了 yield return,以一种函数式编程的写法来延迟实际对节点的操作。
///
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)
=>
recurse
||
(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 团队的一个美女,推荐订阅或关注她的博客)
以上是大佬教程为你收集整理的Silverlight 里如何实现隐式样式全部内容,希望文章能够帮你解决Silverlight 里如何实现隐式样式所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。