我正在尝试通过 Windows 8 Metro C# App 中的反射加载自定义控件库,该库已加载但未加载 generic.xaml 中指定的样式,最终我尝试通过将 generic.xaml 设为嵌入式资源来加载它然后,将 Generic.xaml 提取到一个位置并将其位置指定为 ResourceDictionary 对象的 uri,但它会引发错误
"Failed to create a 'System.Type' from the text local:CustomControl1"
我无法创建 nuget 包或扩展 SDK,因为不幸的是,这不是我的要求,下面是我编写的示例代码,用于复制 generic.xaml 并将其加载到资源字典中
public sealed class CustomControl1 : Control
{
public CustomControl1()
{
this.DefaultStyleKey = typeof(CustomControl1);
Assembly CurrentAssembly = typeof(CustomControl1).GetTypeInfo().Assembly;
var names = CurrentAssembly.GetManifestResourceNames();
var stream = CurrentAssembly.GetManifestResourceStream(names.First());
//generic.xaml is an embedded resource in the current assembly
if (stream != null)
{
//created new generic.xaml here
var file = ApplicationData.Current.LocalFolder.CreateFileAsync("Generic.xaml", CreationCollisionOption.ReplaceExisting).Completed = (o, a) =>
{
var storageFile = o.GetResults();
var s = storageFile.OpenStreamForWriteAsync().Result;
var length = (int)stream.Length;
byte[] bytes = new byte[length];
int output = stream.Read(bytes, 0, length);
s.Write(bytes, 0, length);
s.Flush();
s.Dispose();
var asyncResult = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
var resourceDict = new ResourceDictionary();
var uri = new Uri("ms-appdata:///local/" + storageFile.Name);
resourceDict.Source = uri;
});
};
}
}
// OnApplyTemplate is not called without loading the style from generic.xaml
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
}
下面的代码是我在自定义控件库的构造函数中写的,这样就可以不用generic.xaml来设置控件模板了
在这里,由于属性 TargeType="local:CustomControl1" 不存在,因此控件被正确加载,因为我在构造函数中加载了样式,所以调用 OnApplyTemplate
StringBuilder sb = new StringBuilder();
sb.Append(@"<ControlTemplate
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
xmlns:d=""http://schemas.microsoft.com/expression/blend/2008""
xmlns:mc=""http://schemas.openxmlformats.org/markup-compatibility/2006"">");
sb.Append(@"<Border Background=""{TemplateBinding
Background}""
BorderBrush=""{TemplateBinding BorderBrush}""
BorderThickness=""{TemplateBinding BorderThickness}"">
<Grid>
<Button x:Name=""Tbx1"" Content=""Hello World"" Foreground=""HotPink""
HorizontalAlignment=""Stretch"" VerticalAlignment=""Stretch""/>
</Grid>
</Border>");
sb.Append(@"</ControlTemplate>");
this.Template = (ControlTemplate)XamlReader.Load(sb.ToString());
但问题是使用 XamlReader 加载所有样式不是一个好主意,除非我们没有选项。因为可能有各种依赖样式也必须加载。