24

Windowsフォームアプリケーションに追加されているWPFコントロールライブラリがあります。コントロールをローカライズできるようにしたいのですが、コードを複製せずにこれを完全に実行する方法がわかりません。これが私が今していることです

基本的に、Windowsフォームアプリでは、メインアプリケーションが起動する前に、フォームアプリ内にあるApp.xamlをインスタンス化しています(フォームアプリ内にもあるリソースへのリンクが含まれています)。これは実行時に完全に機能します。

ただし、私のユーザーコントロールにはすべてがありContent="{StaticResource SomeVariableName}"、最終的には空白になります。これを修正するには、app.xamlと、Windowsフォームアプリのリソースディクショナリと一致する適切なリソースディクショナリをコントロールライブラリに追加します。ただし、これは重複したコードです。

私がすでに役に立たなかったこと:

  • フォームアプリ内からユーザーコントロールライブラリ内にあるApp.xamlをインスタンス化します。リソースへのURIがローカルリソースディクショナリではなく埋め込みリソースを探しているため、これは機能しません(その後、ビルド時にコントロールからフォームアプリ内の適切な場所にリソースファイルをコピーするだけで済みます)。ここでDeferrableContentを活用できますか?ただし、この属性とその使用方法について私が知る限り、オンラインはあまりありません。
  • アプリと辞書の両方にポストビルドを使用したいのですが、アプリのインスタンス化は、私が知る限り、コンパイルされたApp.xamlへの静的参照です。したがって、App.xamlは少なくともフォーム内に存在する必要があります
    • ポストビルドでresourcedictionary.xamlを移動して、複製されたApp.xamlを作成しようとしました。複製されたapp.xamlはそれが原動力であり、とにかくコントロールからの1つに依存したくない場合があるので、大丈夫だと思いました(これにより、App.xamlをコントロールに含める必要があるかどうか疑問に思います。埋め込みリソースを使用するデフォルトを許可したい場合を除いて...)URIが指しているはずの場所にリソースが配置されていても、リソースが見つからないと言って失敗しました。逆コンパイルされたコードはUri resourceLocater = new Uri("/WindowsFormsApplication3;component/app.xaml", UriKind.Relative);

それで、これが機能し、コンポーネントのデフォルトを設計時に表示し、重複を回避できるようにする方法はありますか?または、この場合の複製は大丈夫ですか?2番目の箇条書きのサブアイテムに問題がないように見える場合(ビルドコピーされたリソース辞書を使用してApp.xamlを複製)、コンポーネントレベルのアイテムではなく、ファイルレベルのアイテムを検索するにはどうすればよいですか?

私が注意を払った最後の質問(そして必要に応じてこれを個別に投稿することができます)。私のApp.xamlはコードに組み込まれているため、とにかくその場で新しいResourceDictionariesを作成することはできません。これを行う方法はありますか?

最後のオプション...おそらく最高のもの? -とにかくAndrevanHeerwaardeのコードを使用する予定なので、ファイルの存在を確認して、その場でマージされたリソースとして追加する必要がありますか?基本的に、デフォルトの埋め込みResourceDictionaryにリンクする1つのApp.xamlをユーザーコントロールに配置します。そして、コードにその場で適切なローカライズされたリソースを探しさせますか?これは相対的なファイルパスである可能性がありますか?ここで私が見る唯一の欠点は、デフォルトをその場で変更できないことです...おそらく、指定された場所で(ある種の規則を使用して)その外観を持ち、組み込みのものよりも優先される可能性がありますか?

ああ、埋め込みリソースが必要ない理由は、ビルドのデプロイ後にエンドユーザーが新しいローカライズされたリソースを追加/変更できるようにするためです。

これをよりよく視覚化するのに役立つ場合は、コードを追加できます。お知らせください。

アップデート

私は今、ローカライズだけでなく、スタイリングに関するさらなる問題に直面しています。

コントロールの1つにある内部ボタンの1つの例を次に示します。

<Button Style="{StaticResource GrayButton}"

私が試した/考えた他のいくつかのこと:

  • ライブラリプロジェクトではApplicationDefinitionsが許可されていないため、ResourceDictionaryを設定してapp.xaml(使用されることはありません)を作成できません。これをコントロールのリソースに埋め込むことはできますが、それは常にアプリケーションレベルのリソースよりも優先され、カスタマイズ性が失われます。

これは実際に私が探しているもののように聞こえる接続ケースですが、これに対する実際の解決策は提供されていません

私が考えることができる(そしてまだ試していない)解決策(トップを超えて..うまくいかない)も、私が単純であるべきだと思う何かのための多くの仕事のように思えます。ただし、バインドできるいくつかの依存関係プロパティをコントロールに作成し、コントロールを使用するプロジェクトによってそれらをオーバーライドできるようにすることができる場合があります。私が言ったように、それは非常に単純な要求のために多くの仕事のように思えます:)。これでもうまくいくでしょうか?そしてもっと重要なことに、私が見逃しているより良い、より単純な解決策はありますか?

4

3 に答える 3

15

私は一度この問題に遭遇しましたが、「リソースは標準辞書のキーによってインデックス付けされたオブジェクトです」というもの全体を削除することで問題を解決しました。

つまり、あるプロジェクトでリソースを定義し、その「キー」によって別のプロジェクトでリソースを参照するという単純な事実は、正気の人にグースバンプを与えるはずです。強い参照が欲しかった。

この問題に対する私の解決策は、リソースxamlファイルを各リソースのプロパティを持つ静的クラスに変換するカスタムツールを作成することでした。

したがって、MyResources.xaml:

<ResourceDictionary>
  <SolidColorBrush x:Key="LightBrush" ... />
  <SolidColorBrush x:Key="DarkBrush" ... />
</ResourceDictionary>

MyResources.xaml.csになります

public static class MyResources {

  static MyResources() {
    // load the xaml file and assign values to static properties
  }

  public static SolidColorBrush LightBrush { get; set; }
  public static SolidColorBrush DarkBrush { get; set; }

}

x:Staticリソースを参照するには、次の代わりに使用できますStaticResource

<Border 
   Fill="{x:Static MyResources.LightBrush}"
   BorderBrush="{x:Static MyResources.DarkBrush}"
   ... />

これで、リソースの強力な参照、オートコンプリート、コンパイル時のチェックが可能になりました。

于 2012-04-26T13:16:57.810 に答える
0

私もスタイリングテーマと利用可能な静的リソースの処理に問題がありました。そこで、基本的に、以前のリンクされた質問のMERGEDリソースのように、すべてネストされて使用されるテーマしか持たないスタンドアロンライブラリを作成しました。

次に、Windowsフォーム(.xaml)で、そのライブラリへの参照を配置します。

<Window x:Class="MyAppNamespace.MyView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ... />

  <Window.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <!-- Common base theme -->
        <ResourceDictionary   Source="pack://application:,,,/MyLibrary;component/Themes/MyMainThemeWrapper.xaml" />
        </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
  </Window.Resources>

  <Rest of XAML for the WPF window>

</Window>

「コンポーネント」は、指定された「MyLibrary」プロジェクトのルートを参照しているように見えます。実際のプロジェクトでは、「Themes」というサブフォルダーを作成したため、ソースには...; component / Themes/..が含まれています。

「MyMainThemeWrapper.xaml」は、ネストされたマージされたリソースディクショナリに非常によく似ており、他のライブラリからすべてを完全に認識します。

于 2012-04-20T15:58:59.920 に答える
0

これがあなたの問題に対する私の部分的な解決策です。緩いリソースを処理しようとはしていませんが、WinFormsとWPFの間でリソースを共有することである程度の成功を収めています。

  • .ResXファイル(Resources.resx、Resources.fr.resxなど)にリソースを含めるためのクラスライブラリを作成します
  • WPFユーザーコントロールライブラリにWPFコントロールを作成する
  • WinFormsホストを作成します
  • Infralution.Localization.Wpfマークアップ拡張機能とカルチャマネージャーを使用して、WPFからリソースライブラリ内のリソースを参照します。

    <TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/>
    
  • WPFユーザーコントロールのコンテンツを、コントロールテンプレートとして1つ以上のリソースディクショナリに配置します。

    <ControlTemplate x:Key="TestTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
    
            <TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/>
        </Grid>
    </ControlTemplate>
    
  • ユーザーコントロールでリソーステンプレートを使用する

    <UserControl x:Class="WpfControls.UserControl1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300" >
        <UserControl.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="ResourceDictionary.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </UserControl.Resources>
        <ContentControl Template="{StaticResource TestTemplate}" />
    </UserControl>
    
  • 物事を機能させるために数行のコードを追加します

    public partial class UserControl1 : UserControl
    {
        // we require a reference to the resource library to ensure it's loaded into memory
        private Class1 _class1 = new Class1();
    
        public UserControl1()
        {
            // Use the CultureManager to switch to the current culture
            CultureManager.UICulture = Thread.CurrentThread.CurrentCulture;
    
            InitializeComponent();
        }
    }
    

これがWindowsFormsHost.7zと呼ばれる簡単なデモアプリです

于 2012-04-25T20:11:49.080 に答える