I am trying to load a custom control library via reflection in windows 8 Metro C# App, the library is loaded but the styles specified in generic.xaml are not loaded, eventually I tried to load the generic.xaml by making it as an Embedded resource and ,then extracted the Generic.xaml to a location and specified the location of it as uri of a ResourceDictionary object, but it throws an error
"Failed to create a 'System.Type' from the text local:CustomControl1"
I cannot create a nuget package or extension SDK as unfortunately that is not my requirement, Below sample code I wrote to copy the generic.xaml and load it in a resource dictionary
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();
}
}
The below code I wrote in the custom control library's constructor, so that the control template can be set without generic.xaml
Here since the attribute TargeType="local:CustomControl1" is not present the control gets loaded properly, here since I loaded the style in the constructor, the OnApplyTemplate gets called
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());
but the problem is loading all the styles using XamlReader is not a good idea, unless we are out of Options. As there may be various dependent styles which too have to be loaded.
Check out how they do it in the WinRTXamlToolkit . They create the Generic.xaml
for the project and include all control templates inside of separate styles in different ResourceDictionary
s packaged next to the respective controls.
To put it more simply (for Templated controls, like you are using):
Make two files for each control, MyControl.cs
and MyControl.xaml
In MyControl.cs
in your MyControl
constructor, set the StyleKey
to be typeof(MyControl)
(like you are doing currently).
Make sure there is a style for your control with TargetType
set to the type of your control. Do the same thing for the ControlTemplate
that you have as the Template
property set in the Style
.
In MyControl.xaml
, make a ResourceDictionary
that stores all of the necessary styles, templates, and resources.
In your Generic.xaml
, create a MergedDictionaries
tag under the root and create a ResourceDictionary
for each control, setting the Source to the full path of MyControl.xaml
Set each of the .xaml files to be build type of Page
with CustomTool
set to MSBuild:Compile
.
Hope this helps and Happy coding!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.