您的位置:首页 > 其它

x:Static 和 StaticResource 标记扩展

2014-02-07 17:50 246 查看
标记扩展(markup extension)是 XAML 语言以及 XAML 服务的 .NET 实现的常规功能。 本文简单论述x:Static 和 StaticResource 标记扩展。

Xaml 示例

<Window.Resources>
<FontFamily x:Key="CustomFont">Verdana</FontFamily>
</Window.Resources>


<TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily},Path=Source}"></TextBlock>
<TextBlock Text="{Binding Source={StaticResource CustomFont},Path=Source}"></TextBlock>


当x:static与默认 XAML Schema Context一起运行时,对静态属性的查找操作可以由 .NET Framework XAML Serivces及其 XAML Readers和 XAML Writers执行。如下所示,通过ServiceProvider 得到其Xaml Type,进而用反射来取得值。

using System;
using System.ComponentModel;
using System.Runtime;
using System.Runtime.CompilerServices;

namespace System.Windows.Markup
{
[TypeConverter(typeof(StaticExtensionConverter)),MarkupExtensionReturnType(typeof(object))]
public class StaticExtension : MarkupExtension
{
public StaticExtension();

public StaticExtension(string member);

public Type MemberType { get; set; }

public override object ProvideValue(IServiceProvider serviceProvider);
}
}


/// <summary>
///  Return an object that should be set on the targetObject's targetProperty
///  for this markup extension.  For a StaticExtension this is a static field
///  or property value.
/// </summary>
/// <param name="serviceProvider">Object that can provide services for the markup extension.
/// <returns>
///  The object to set on this property.
/// </returns>
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_member == null)
{
throw new InvalidOperationException(SR.Get(SRID.MarkupExtensionStaticMember));
}

object value = null;
Type type = MemberType;
string fieldString = null;
string memberFullName = null;
if (type != null)
{
fieldString = _member;
memberFullName = type.FullName + "." + _member;
}
else
{
memberFullName = _member;

// Validate the _member
int dotIndex = _member.IndexOf('.');
if (dotIndex < 0)
{
throw new ArgumentException(SR.Get(SRID.MarkupExtensionBadStatic, _member));
}

// Pull out the type substring (this will include any XML prefix, e.g. "av:Button")
string typeString = _member.Substring(0, dotIndex);
if (typeString == string.Empty)
{
throw new ArgumentException(SR.Get(SRID.MarkupExtensionBadStatic, _member));
}

// Get the IXamlTypeResolver from the service provider
IXamlTypeResolver xamlTypeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
if (xamlTypeResolver == null)
{
throw new ArgumentException(SR.Get(SRID.MarkupExtensionNoContext, GetType().Name, "IXamlTypeResolver"));
}

// Use the type resolver to get a Type instance
type = xamlTypeResolver.Resolve(typeString);

// Get the member name substring
fieldString = _member.Substring(dotIndex + 1, _member.Length - dotIndex - 1);
if (fieldString == string.Empty)
{
throw new ArgumentException(SR.Get(SRID.MarkupExtensionBadStatic, _member));
}
}

// Use the built-in parser for enum types
if (type.IsEnum)
{
return Enum.Parse(type, fieldString);
}

// For other types, reflect
bool found = false;
object fieldOrProp = type.GetField(fieldString, BindingFlags.Public |
BindingFlags.FlattenHierarchy | BindingFlags.Static);
if (fieldOrProp == null)
{
fieldOrProp = type.GetProperty(fieldString, BindingFlags.Public |
BindingFlags.FlattenHierarchy | BindingFlags.Static);
if (fieldOrProp is PropertyInfo)
{
value = ((PropertyInfo)fieldOrProp).GetValue(null, null);
found = true;
}
}
else if (fieldOrProp is FieldInfo)
{
value = ((FieldInfo)fieldOrProp).GetValue(null);
found = true;
}

if (found)
{
return value;
}
else
{
throw new ArgumentException(SR.Get(SRID.MarkupExtensionBadStatic, memberFullName));
}
}


StaticResource 标记扩展通过查找对已定义资源的引用,指定的 ResourceKey 应与某个现有资源对应,此现有资源使用页、应用程序、可用控件主题和外部资源或系统资源中某一级别的 x:Key 指令来标识。 资源查找按照该顺序执行。

using System;
using System.Runtime;
using System.Windows.Markup;

namespace System.Windows
{
[MarkupExtensionReturnType(typeof(Object))]
[Localizability(LocalizationCategory.NeverLocalize)]
public class StaticResourceExtension : MarkupExtension
{
public StaticResourceExtension();

public StaticResourceExtension(object resourceKey);

public object ResourceKey { get; set; }

public override object ProvideValue(IServiceProvider serviceProvider);
}
}


/// <summary>Returns an object that should be set on the property where this extension is applied. For <see cref="T:System.Windows.StaticResourceExtension" />, this is the object found in a resource dictionary, where the object to find is identified by the <see cref="P:System.Windows.StaticResourceExtension.ResourceKey" />.</summary>
/// <returns>The object value to set on the property where the markup extension provided value is evaluated.</returns>
/// <param name="serviceProvider">Object that can provide services for the markup extension.</param>
/// <exception cref="T:System.InvalidOperationException">
///   <paramref name="serviceProvider" /> was null, or failed to implement a required service.</exception>
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (this.ResourceKey is SystemResourceKey)
{
return (this.ResourceKey as SystemResourceKey).Resource;
}
return this.ProvideValueInternal(serviceProvider, false);
}
internal object ProvideValueInternal(IServiceProvider serviceProvider, bool allowDeferredReference)
{
object obj = this.TryProvideValueInternal(serviceProvider, allowDeferredReference, false);
if (obj == DependencyProperty.UnsetValue)
{
throw new Exception(SR.Get("ParserNoResource", new object[]
{
this.ResourceKey.ToString()
}));
}
return obj;
}
internal object TryProvideValueInternal(IServiceProvider serviceProvider, bool allowDeferredReference, bool mustReturnDeferredResourceReference)
{
DeferredResourceReference prefetchedValue = this.PrefetchedValue;
object obj;
if (prefetchedValue == null)
{
obj = this.FindResourceInEnviroment(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference);
}
else
{
obj = this.FindResourceInDeferredContent(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference);
if (obj == DependencyProperty.UnsetValue)
{
obj = (allowDeferredReference ? prefetchedValue : prefetchedValue.GetValue(BaseValueSourceInternal.Unknown));
}
}
return obj;
}


internal object FindResourceInDeferredContent(IServiceProvider serviceProvider, bool allowDeferredReference, bool mustReturnDeferredResourceReference)
{
ResourceDictionary resourceDictionary = this.FindTheResourceDictionary(serviceProvider, true);
object obj = DependencyProperty.UnsetValue;
if (resourceDictionary != null)
{
obj = resourceDictionary.Lookup(this.ResourceKey, allowDeferredReference, mustReturnDeferredResourceReference, false);
}
if (mustReturnDeferredResourceReference && obj == DependencyProperty.UnsetValue)
{
obj = new DeferredResourceReferenceHolder(this.ResourceKey, obj);
}
return obj;
}

private object FindResourceInAppOrSystem(IServiceProvider serviceProvider, bool allowDeferredReference, bool mustReturnDeferredResourceReference)
{
object result;
if (!SystemResources.IsSystemResourcesParsing)
{
object obj;
result = FrameworkElement.FindResourceFromAppOrSystem(this.ResourceKey, out obj, false, allowDeferredReference, mustReturnDeferredResourceReference);
}
else
{
result = SystemResources.FindResourceInternal(this.ResourceKey, allowDeferredReference, mustReturnDeferredResourceReference);
}
return result;
}
private object FindResourceInEnviroment(IServiceProvider serviceProvider, bool allowDeferredReference, bool mustReturnDeferredResourceReference)
{
ResourceDictionary resourceDictionary = this.FindTheResourceDictionary(serviceProvider, false);
if (resourceDictionary != null)
{
return resourceDictionary.Lookup(this.ResourceKey, allowDeferredReference, mustReturnDeferredResourceReference, false);
}
object obj = this.FindResourceInAppOrSystem(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference);
if (obj == null)
{
obj = DependencyProperty.UnsetValue;
}
if (mustReturnDeferredResourceReference && !(obj is DeferredResourceReference))
{
obj = new DeferredResourceReferenceHolder(this.ResourceKey, obj);
}
return obj;
}


private ResourceDictionary FindTheResourceDictionary(IServiceProvider serviceProvider, bool isDeferredContentSearch)
{
IXamlSchemaContextProvider xamlSchemaContextProvider = serviceProvider.GetService(typeof(IXamlSchemaContextProvider)) as IXamlSchemaContextProvider;
if (xamlSchemaContextProvider == null)
{
throw new InvalidOperationException(SR.Get("MarkupExtensionNoContext", new object[]
{
base.GetType().Name,
"IXamlSchemaContextProvider"
}));
}
IAmbientProvider ambientProvider = serviceProvider.GetService(typeof(IAmbientProvider)) as IAmbientProvider;
if (ambientProvider == null)
{
throw new InvalidOperationException(SR.Get("MarkupExtensionNoContext", new object[]
{
base.GetType().Name,
"IAmbientProvider"
}));
}
XamlSchemaContext schemaContext = xamlSchemaContextProvider.SchemaContext;
XamlType xamlType = schemaContext.GetXamlType(typeof(FrameworkElement));
XamlType xamlType2 = schemaContext.GetXamlType(typeof(Style));
XamlType xamlType3 = schemaContext.GetXamlType(typeof(FrameworkTemplate));
XamlType xamlType4 = schemaContext.GetXamlType(typeof(Application));
XamlType xamlType5 = schemaContext.GetXamlType(typeof(FrameworkContentElement));
XamlMember member = xamlType5.GetMember("Resources");
XamlMember member2 = xamlType.GetMember("Resources");
XamlMember member3 = xamlType2.GetMember("Resources");
XamlMember member4 = xamlType2.GetMember("BasedOn");
XamlMember member5 = xamlType3.GetMember("Resources");
XamlMember member6 = xamlType4.GetMember("Resources");
XamlType[] types = new XamlType[]
{
schemaContext.GetXamlType(typeof(ResourceDictionary))
};
IEnumerable<AmbientPropertyValue> allAmbientValues = ambientProvider.GetAllAmbientValues(null, isDeferredContentSearch, types, new XamlMember[]
{
member,
member2,
member3,
member4,
member5,
member6
});
List<AmbientPropertyValue> list = allAmbientValues as List<AmbientPropertyValue>;
for (int i = 0; i < list.Count; i++)
{
AmbientPropertyValue ambientPropertyValue = list[i];
if (ambientPropertyValue.Value is ResourceDictionary)
{
ResourceDictionary resourceDictionary = (ResourceDictionary)ambientPropertyValue.Value;
if (resourceDictionary.Contains(this.ResourceKey))
{
return resourceDictionary;
}
}
if (ambientPropertyValue.Value is Style)
{
Style style = (Style)ambientPropertyValue.Value;
ResourceDictionary resourceDictionary2 = style.FindResourceDictionary(this.ResourceKey);
if (resourceDictionary2 != null)
{
return resourceDictionary2;
}
}
}
return null;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: