4

クライアントごとにカスタマイズできるようにするアプリケーションを WPF (.Net 3.5) で作成しています。リソースを外部の xaml (テーマ) ファイルに抽象化しました。として構築されたxamlファイルを使用するPageと、これは完璧に機能します。

XamlReader今、テーマの xaml ファイルを動的にロードするために使用したいと考えています。このようにして、私がアプリケーションをコンパイルし、他の人が (クライアントごとに) アプリをカスタマイズできます。再コンパイルやソース コードへのアクセスは必要ありません。これが私がやっていることのスナップショットです:

Directory.GetFiles(pathToThemeDirectory).Each((file) =>
{
     using (Stream stream = new FileStream(file, FileMode.Open))
     {
          var dir = Directory.GetCurrentDirectory();
          var dict = XamlReader.Load(stream) as ResourceDictionary;
          Application.Current.Resources.MergedDictionaries.Add(dict);
     }
});

これで、Xaml が正しく解析されるようになりました。ただし、次のようなエラーが表示されるようになりました。

Cannot convert string '/Path/To/Image/File.ico' in attribute 'Icon' to object of 
type 'System.Windows.Media.ImageSource'. Cannot locate resource
'/Path/To/Image/File.ico'.  Error at object 'System.Windows.Setter'

クライアントごとにこれらのリソース (ロゴ画像など) を変更できるようにしたいので、ビルド アクションを からResourceに変更Noneし、常に出力ディレクトリにコピーするように指示しました。

実行時に Xaml を解析し、構成を変更して、アセンブリでコンパイルする必要のないイメージ リソースを取得する方法について何か提案はありますか? または、私は完全にベースから外れており、このテーマのカスタマイズを実現するためのより良い方法はありますか?


アップデート:

エラーが発生している正確な行は次のとおりです。

<Style x:Key="MainWindow">
    <Setter Property="Window.Icon" Value="/Assets/icon.ico" />
</Style>

しかし、それはこれがロードされた最初のアセットだからです。別の例を次に示します。

<ImageBrush x:Key="NavigationBackgroundImage" ImageSource="Assets/bg.png" TileMode="Tile" Stretch="UniformToFill"/>

これらは、次の方法でアクセスするスタイルで使用されます。

{StaticResource MainWindow}

また

{StaticResource NavigationBackgroundImage}
4

1 に答える 1

3

このブログによると、ParserContext を作成する必要があるようです。

その例では、彼は次のことを行っていました。

var resourceDictionary = XamlReader.Load(fileStream) as ResourceDictionary;
if(resourceDictionary != null)
{
    Resources.MergedDictionaries.Add(resourceDictionary)
}

しかしその後、コードは次のように変更されました。

var applicationDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if(!String.IsNullOrEmpty(applicationDirectory ))
{

    var runtimeResourcesDirectory = Path.Combine(applicationDirectory , "RuntimeResources");
    var pc = new ParserContext
    {
        BaseUri = new Uri(runtimeResourcesDirectory , UriKind.Absolute)
    };
    if(Directory.Exists(runtimeResourcesDirectory ))
    {
        foreach (string resourceDictionaryFile in Directory.GetFiles(runtimeResourcesDirectory , "*.xaml"))
        {
            using (Stream s = File.Open(resourceDictionaryFile, FileMode.Open, FileAccess.Read))
            {
                try
                {
                    var resourceDictionary = XamlReader.Load(s, pc) as ResourceDictionary;
                    if (resourceDictionary != null)
                    {
                        Resources.MergedDictionaries.Add(resourceDictionary);
                    }
                }
                catch
                {
                    MessageBox.Show("Invalid xaml: " + resourceDictionaryFile);
                }
            }
        }
    }
}

お役に立てれば!

于 2012-07-11T16:58:39.920 に答える