2014-02-05 2 views
1

Windows 8 Metro C# App에서 리플렉션을 통해 사용자 지정 컨트롤 라이브러리를로드하려고하는데 라이브러리가로드되었지만 generic.xaml에 지정된 스타일이로드되지 않았습니다. 결국 generic.xaml을로드하여로드하려고 시도했습니다. 자원을 내장하고, 다음 위치에 generic.xaml을 추출하고 ResourceDictionary에 개체의 URI로의 위치를 ​​지정하지만, 내가 nuget 패키지 또는 확장 SDK를 같은 불행하게도 만들 수 없습니다Windows Store 앱 : 맞춤 컨트롤 클래스 라이브러리에서 반사를 통해 스타일로드, OnApplyTemplate이 호출되지 않습니까?

"Failed to create a 'System.Type' from the text local:CustomControl1" 

에서 오류가 발생하는 내 요구 사항이 아닙니다. 아래 샘플 코드는 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(); 
    } 
} 

컨트롤 템플릿은 속성 = TARGETYPE 때문에 여기에 generic.xaml을

없이 설정 될 수 있도록 내가, 사용자 지정 컨트롤 라이브러리의 생성자에 쓴 아래 코드 : 컨트롤이로드되는 "지역 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

안녕하세요 네이트, 답장을 보내 주셔서 감사합니다. –

+0

내 리소스 사전 섹션이 아래에 표시됩니다. –

답변

1

WinRTXamlToolkit에서 어떻게 동작하는지 확인하십시오. 프로젝트에 대해 Generic.xaml을 만들고 각 컨트롤 옆에 다른 ResourceDictionary 패키지에있는 별도의 스타일 안에 모든 컨트롤 템플릿을 포함시킵니다. (당신이 사용하고있는 것처럼, 템플릿 기반 컨트롤)

더 간단히 말해 :

  • MyControl.cs에서 두 각 컨트롤 파일, MyControl.csMyControl.xaml

  • 를 확인하여 MyControl 생성자에서 설정 StyleKeytypeof(MyControl)입니다 (현재하고있는 것과 같습니다).

  • 조절 유형이 TargetType으로 설정되어 있는지 확인하십시오. 속성이 Style에 설정되어있는 ControlTemplate에 대해 동일한 작업을 수행하십시오.

  • MyControl.xaml에는 필요한 스타일, 템플릿 및 리소스를 모두 저장하는 ResourceDictionary을 만드십시오. 당신의 Generic.xaml에서

  • , 빌드가되도록 .xaml 파일을 각각 설정 MyControl.xaml

의 전체 경로에 소스를 설정, 루트 아래 MergedDictionaries 태그를 생성하고 각각의 제어를위한 ResourceDictionary를 만들 유형은 Page이고 CustomToolMSBuild:Compile입니다.

호프가 도움이되고 즐거운 코딩이 되길 바랍니다!

+0

Nate, –

+0

Assembly assem = Assembly.Load (새 AssemblyName ("MyControlAssembly")); CType = assem.ExportedTypes.FirstOrDefault (p => p.Name == "MyControl"); 개체 ob = Activator.CreateInstance (CType); // 여기에있는 격자는 현재 프로젝트의 MainPage.xaml에있는 격자 객체입니다 tgrid.Children.Add (FrameworkElement로 ob); –

+0

여전히 동일한 예외를 "로컬 : 텍스트에서 'System.Type'을 만들지 못했습니다. MyControl" –