web-dev-qa-db-ja.com

WPFでテンプレートウィンドウを作成するにはどうすればよいですか?

だから私はたくさんのウィンドウを持ち、すべて同じ基本的なレイアウトを持つアプリケーションを構築しています:

  1. メインウィンドウ
  2. 上隅のロゴ
  3. タイトルブロック
  4. 下部にあるステータス表示
  5. ウィンドウ固有のコントロール用の領域。

現時点では、すべてのウィンドウでこの構造を再作成する必要があります。理想的には、このレイアウトを1つの場所で、おそらく使いやすさのためにカスタムWindowサブクラスにコーディングする必要があります。誰かがどのように始めるか、または同様の問題の以前の経験について何か手がかりを持っていますか?

18
NoizWaves

以下に示すように、これを実現するためにウィンドウをターゲットとする新しいControlTemplateを作成できます。

<ControlTemplate x:Key="WindowControlTemplate1" TargetType="{x:Type Window}">
    <Border 
        Background="{TemplateBinding Background}" 
        BorderBrush="{TemplateBinding BorderBrush}" 
        BorderThickness="{TemplateBinding BorderThickness}"
        >
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="0.93*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.21*"/>
                <ColumnDefinition Width="0.79*"/>
            </Grid.ColumnDefinitions>

            <ContentPresenter 
                Grid.ColumnSpan="2" 
                Grid.Row="1" 
                Content="{TemplateBinding Content}" 
                ContentTemplate="{TemplateBinding ContentTemplate}"
                />
            <ResizeGrip 
                HorizontalAlignment="Right" 
                x:Name="WindowResizeGrip" 
                VerticalAlignment="Bottom" 
                IsTabStop="False" 
                Visibility="Collapsed" 
                Grid.Column="1" 
                Grid.Row="2"
                />
            <TextBlock Text="My Logo" />
            <TextBlock Grid.Column="1" Text="My Title"/>
            <StatusBar Height="20" Grid.ColumnSpan="2" Grid.Row="2"/>
        </Grid>
    </Border>

    <ControlTemplate.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="ResizeMode" Value="CanResizeWithGrip"/>
                <Condition Property="WindowState" Value="Normal"/>
            </MultiTrigger.Conditions>
            <Setter Property="Visibility" TargetName="WindowResizeGrip" Value="Visible"/>
        </MultiTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
32
Ian Oakes

大きなアーキテクチャの変更を行う勇気がある場合は、MicrosoftのPatterns&Practicesの担当者から CompositeWPF (以前はコードネームPrism)を検討できます。

興味深いのは、シェル(つまりウィンドウ)で「領域」を定義し、ビューを使用して領域を塗りつぶす機能です。 Model-View-Presenterパターンを使用して、モデルからの「ビュー」の独立した開発を可能にします。シェルは領域を定義するだけで、配置されているものに直接結合されないため、時間の経過とともに簡単に再配置できます。主に、これはシェルをビューから分離し、ビューを相互に分離し、ユニットテストを容易にするのに役立ちます...何とか何とか何とか。

あなたの状況はCompositeWPFが対処することを意図しているアプリケーションのタイプの1つですが、それは大きなジャンプであり、そもそもあなたを遅くする何かです。

CompositeWPFの一部として、新規参入者を混乱させる可能性のあるさまざまなパターンを採用する必要があります。 UnityContainer、制御の反転、MVP(またはモデル/ビュー/ビューモデル)および依存性注入。

サンプルアプリを最初に困惑させ始めたときのことを思い出すことができます。なぜなら、いったいどのようにいくつかのビューが作成されていたのかが明らかではないからです。 Unityコンテナーはオブジェクトをインスタンス化し、パラメーター化されたコンストラクターを魔法のように呼び出します。

CompositeWPFは、質問に対する洗練されたソリューションですが、単純または単純なソリューションではありません。前回のプロジェクトでCompositeWPFを使用したので、次の適切なアプリケーションで再び使用する予定です。

6
Rhys

最も簡単なアプローチは、ウィンドウ固有のコントロール用にWPFの「ページ」を作成し、メインウィンドウに「フレーム」を配置することです。この方法で素敵なナビゲーションを作成することもできます。

2
Hades32