2009-05-26 4 views
42

最初にいくつかの背景:私はアプリケーションで作業しており、MVVMの規約に従っています。私がしたいことの1つは、アプリケーションにアプリケーションに異なる「スキン」を与えることです。同じアプリケーションですが、1つのクライアントに対して1つの「スキン」、別のクライアントに異なる「スキン」を表示します。実行時にXAMLをロードしていますか?

私の質問は次のとおりです。
1.実行時にxamlファイルを読み込んで自分のアプリケーションに割り当てることは可能ですか?
2. xamlファイルを別のフォルダにある外部ファイルにすることはできますか?
3.起動時にのみ、アプリケーションを別のxamlファイルに簡単に切り替えることはできますか?

ここで私はこれについての情報を調べる必要がありますか?どのWPFメソッドが存在すればこの機能を処理しますか?

ありがとうございます!

編集:私がしたいと思っている「スキニング」のタイプは、コントロールの外観を変更するだけではありません。アイデアはまったく異なるUIを持っています。異なるボタン、異なるレイアウト。アプリの1つのバージョンがエキスパート向けに完全に機能し、別のバージョンが初心者向けにどのように単純化されるかのようなものです。

答えて

4

XamlReader.Loadを使用して、任意のXAMLをロードできます。

アプリケーションですべてのコントロールをスタイル設定し、アプリケーションリソースディクショナリでこれらのスタイルを定義すると、XamlReader.Loadを使用してXAMLで定義された新しいスタイルを読み込み、リソースディクショナリの一部を読み込まれたXAMLで置き換えることができます。それに応じてコントロールの外観が変わります。

33

ヤコブ・クリステンセンが指摘したように、あなたがXamlReader.Loadを使用したい任意のXAMLを読み込むことができます。これはスタイルだけには適用されませんが、UIElementも同様です。

UIElement rootElement; 
FileStream s = new FileStream(fileName, FileMode.Open); 
rootElement = (UIElement)XamlReader.Load(s); 
s.Close(); 

などのXAMLをロードするだけです。適切な要素のコンテンツとして設定することができます。

<Window x:Class="MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Foo Bar"> 
    <Grid x:Name="layoutGrid"> 
     <!-- any static elements you might have --> 
    </Grid> 
</Window> 

のためにあなたがgridrootElementを追加することができます:あなたは自然にも手動でコードビハインドでrootElement内の要素のための任意のイベントを接続する必要があります

layoutGrid.Children.Add(rootElement); 
layoutGrid.SetColumn(rootElement, COLUMN); 
layoutGrid.SetRow(rootElement, ROW); 

。例として、あなたのrootElementPath Sの束とCanvasが含まれている、あなたはこのようなPath s'のMouseLeftButtonDownイベントを割り当てることができます仮定:

Canvas canvas = (Canvas)LogicalTreeHelper.FindLogicalNode(rootElement, "canvas1"); 
foreach (UIElement ui in LogicalTreeHelper.GetChildren(canvas)) { 
    System.Windows.Shapes.Path path = ui as System.Windows.Shapes.Path; 
    if (path != null) { 
     path.MouseLeftButtonDown += this.LeftButtonDown; 
    } 
} 

私はその場でXAMLファイルを切り替えてみましたので、私ていませんでしたそれが本当にうまくいくかどうかは言えません。

+0

こんにちは! これは私が探しているものであるようです。私が欠けている唯一のビットは、ソリューションの一部である.xamlファイルを処理する方法です。私はどうやってそれらをロードするのですか? – djcouchycouch

+0

私が取り組んでいるアプリケーションでは、ソリューションにXAMLファイルを保存し、ビルドアクションを「なし」に設定し、新しい場合はVisual Studioで出力ディレクトリにファイルをコピーします。上記の最初のコードスニペットを使用して読み込みます。 –

+0

ここで私が探していたのは、xamlをリソースとしてロードすることです http://msdn.microsoft.com/en-us/library/aa970494.aspx – djcouchycouch

0

チェックアウトhttp://www.codeproject.com/Articles/19782/Creating-a-Skinned-User-Interface-in-WPF - Josh SmithがWPFでスキニングを行う方法について素晴らしい記事を書いています。

public class DynamicXamlLoader : MarkupExtension 
{ 
    public DynamicXamlLoader() { } 

    public DynamicXamlLoader(string xamlFileName) 
    { 
     XamlFileName = xamlFileName; 
    } 

    public string XamlFileName { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     var provideValue = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; 
     if (provideValue == null || provideValue.TargetObject == null) return null; 

     // get target 
     var targetObject = provideValue.TargetObject as UIElement; 
     if (targetObject == null) return null; 

     // get xaml file 
     var xamlFile = new DirectoryInfo(Directory.GetCurrentDirectory()) 
      .GetFiles(XamlFileName ?? GenerateXamlName(targetObject), SearchOption.AllDirectories) 
      .FirstOrDefault(); 

     if (xamlFile == null) return null; 

     // load xaml 
     using (var reader = new StreamReader(xamlFile.FullName)) 
      return XamlReader.Load(reader.BaseStream) as UIElement; 
    } 

    private static string GenerateXamlName(UIElement targetObject) 
    { 
     return string.Concat(targetObject.GetType().Name, ".xaml"); 
    } 
} 

使用法:

この発見と

4

私はここで、実行時にXAMLのロードを行っているが、私は、XAMLがロードシンプルなマークアップ拡張機能を作っ

Grid grd = new Grid(); 
var grdEncoding = new ASCIIEncoding(); 
var grdBytes = grdEncoding.GetBytes(myXAML); 
grd = (Grid)XamlReader.Load(new MemoryStream(grdBytes)); 
Grid.SetColumn(grd, 0); 
Grid.SetRow(grd, 0); 
parentGrid.Children.Add(grd); 

private String myXAML = @" <Grid xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' Margin='30 10 30 65' VerticalAlignment='Bottom'>" + 
        "<Label Content='Date: 1-Feb-2013' FontFamily='Arial' FontSize='12' Foreground='#666666' HorizontalAlignment='Left'/>" + 
        "<Label Content='4' FontFamily='Arial' FontSize='12' Foreground='#666666' HorizontalAlignment='Center'/>" + 
        "<Label Content='Hello World' FontFamily='Arial' FontSize='12' Foreground='#666666' HorizontalAlignment='Right'/>" + 
       "</Grid>"; 
4

短い例ですMyFirstView.xamlファイルをロードする

そして、これはUserControl全体(Find MySecondView.xamlファイルをロード)を埋めます。

<UserControl x:Class="MySecondView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Content="{wpf:DynamicXamlLoader}" /> 
関連する問題