2014-02-05 44 views
1

我想通過反射加載自定義控制庫在Windows 8 Metro C#應用程序,該庫被加載,但generic.xaml中指定的樣式不加載,最終我試圖加載generic.xaml通過使它作爲嵌入式資源,然後提取Generic.xaml到某個位置,作爲一個資源字典對象的URI指定它的位置,但它拋出一個錯誤Windows應用商店應用:通過反射從自定義控件類庫加載樣式,不調用OnApplyTemplate?

"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 =設置「本地: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是不是一個好主意,除非我們進行選擇的所有樣式。因爲可能有各種各樣的依賴樣式也必須加載。

+0

我注意到你正在創建一個'ResourceDictionary',但似乎沒有在任何地方使用它。在我看來,在你加載樣式的位置(並且出錯),你沒有正確定義'local'命名空間。我仍然不確定爲什麼你需要像這樣加載控件。這樣做是否符合您的要求?或者你可以改變更類似於我發佈的答案嗎? –

+0

嗨Nate,感謝您的回覆, –

+0

我的資源字典的一部分顯示在下面 –

回答

1

看看他們是如何在WinRTXamlToolkit中做到的。他們爲項目創建Generic.xaml,並在各個控件旁邊打包的不同ResourceDictionary中包含單獨樣式中的所有控件模板。

要說得簡單些(對於模板化控件,比如你正在使用):

  • 使兩個文件爲每個控件,MyControl.csMyControl.xaml

  • MyControl.csMyControl構造,設置StyleKeytypeof(MyControl)(就像你現在正在做的那樣)。

  • 確保您的控件有一種風格,TargetType設置爲您的控件類型。對ControlTemplate執行相同的操作,您將Template屬性設置爲Style

  • MyControl.xaml中,創建一個ResourceDictionary,其中存儲所有必需的樣式,模板和資源。

  • 在你Generic.xaml,創建根目錄下MergedDictionaries標籤,併爲每個控制ResourceDictionary,設置源設置每一個文件名爲.xaml的是構建MyControl.xaml

的完整路徑Page的類型,CustomTool設置爲MSBuild:Compile

希望這有助於和快樂的編碼!

+0

我試過你的方式Nate, –

+0

Assembly assem = Assembly.Load(new AssemblyName(「MyControlAssembly」)); 類型CType = assem.ExportedTypes.FirstOrDefault(p => p.Name ==「MyControl」); object ob = Activator.CreateInstance(CType); //這裏t grid是當前項目的MainPage.xaml中的網格對象 tgrid.Children.Add(ob as FrameworkElement); –

+0

它仍然給出了同樣的異常「無法創建一個'System.Type'從文本local:MyControl」 –

相關問題