Приложения для Магазина Windows: загружая стили из библиотеки классов customcontrol с помощью отражения, OnApplyTemplate не вызывается?

Я пытаюсь загрузить пользовательскую библиотеку элементов управления с помощью отражения в Windows 8 Metro C# App, библиотека загружена, но стили, указанные в generic.xaml, не загружены, в конце концов я попытался загрузить generic.xaml, сделав его встроенным ресурсом. и затем извлек Generic.xaml в местоположение и указал его местоположение как URI объекта ResourceDictionary, но он выдает ошибку

"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 не очень хорошая идея, если только у нас нет параметров. Так как могут быть различные зависимые стили, которые тоже должны быть загружены.

1 ответ

Проверьте, как они это делают в WinRTXamlToolkit. Они создают Generic.xaml для проекта и включить все шаблоны управления внутри отдельных стилей в разных ResourceDictionarys упакованы рядом с соответствующими элементами управления.

Проще говоря (для шаблонных элементов управления, которые вы используете):

  • Сделайте два файла для каждого элемента управления, MyControl.cs а также MyControl.xaml

  • В MyControl.cs в вашем MyControl конструктор, установите StyleKey быть typeof(MyControl) (как вы делаете в настоящее время).

  • Убедитесь, что есть стиль для вашего контроля с TargetType установить тип вашего контроля. Сделайте то же самое для ControlTemplate что у вас есть как Template свойство установлено в Style,

  • В MyControl.xaml, делать ResourceDictionary который хранит все необходимые стили, шаблоны и ресурсы.

  • В вашем Generic.xaml, создать MergedDictionaries пометить под корнем и создать ResourceDictionary для каждого элемента управления задайте для источника полный путь MyControl.xaml

Установите для каждого из файлов.xaml тип сборки Page с CustomTool установлен в MSBuild:Compile,

Надеюсь, это поможет и счастливого кодирования!

Другие вопросы по тегам