Viewbox を含むウィンドウがあります。その Viewbox には、既に UserControls として作成したいくつかのビューの 1 つが必要です。MVVM (Model View View-Model) デザイン パターンを使用しています。オンラインで約 1 時間検索しましたが、ContentPresenter
.
2 に答える
依存します。
あなたの主な問題は、 aContentPresenter
がコントロールテンプレート内でのみ使用されることだと思います。ウィンドウに貼り付けて、ウィンドウのコンテンツを表示することを期待することはできません。本当に必要なのは、ContentControlを使用して UI をホストすることだと思います。
モデルをこのコントロールのプロパティにバインドすることによりContent
、そのモデルの予期されるビューを含む DataTemplates を設定できます。簡略化した例を示します。これは設計と一致しない場合がありますが、すべてがどのように連携するかを示しています。
まず、ビューごとに、そのビューのデータ (および相互作用) を管理するモデル (またはビューモデル) を作成します。
public sealed class Dialog : INotifyPropertyChanged // or DependencyObject
{
public string Input {get;set;} // INPC or DP implementation not shown
public ICommand Cancel {get;set;}
// class definition not shown
}
次に、View が ContentPresenter に表示されるように定義します。
<UserControl x:Class="Herp.DialogView"
HideImplementationDetails="true">
<Border BorderBrush="Red" BorderThickness="5">
<TextBlock Text="{Binding Input}" />
<Button Command="{Binding Cancel}">Cancel</Button>
<!-- etc etc -->
</Border>
</UserControl>
次に、ウィンドウに ContentControl と DataTemplate を追加します。
<Window HideImplementationDetailsForBrevityOfXaml="true">
<Window.Resources>
<DataTemplate xmlns:t="clr-namespace:Herp"
DataType="{x:Type t:Dialog}">
<t:DialogView />
</DataTempalte>
</Window.Resources>
<ContentControl Content="{Binding}" />
</Window>
最後に、ウィンドウの DataContext をDialog
モデルに設定します。
public MyWindow()
{
InitializeComponent();
DataContext = new Dialog();
}
ロジックの流れは次のとおりです。
- ウィンドウが作成されます。
- ダイアログ コントロールのインスタンスは、DataContext に設定されます。
- ContentControl のバインディングが更新されます
- が設定されているリソースを検索するデフォルトのDataTemplateSelector
ContentControl
DataTemplate
DataType
typeof(Dialog)
- ウィンドウのリソース内でこの DataTemplate を見つけます
- DataTemplate のコンテンツが読み込まれ、ビジュアルの子として追加されます
ContentControl
Content
が変更されるたびContentControl
に、同じプロセスが繰り返されます。そのため、それぞれが異なる UserControl を含む異なる DataTemplate を持つ多くの異なるモデルを持つことができ、ContentControl のバインディングを更新するたびに、期待されるビューが表示されます。
MVVM では、ViewModel のプロパティをプロパティにバインドしContent
(Current などと呼びます)、ViewModel の現在の状態に応じて、プロパティ内のモデルを期待値に切り替えます。Content
ContentControl 内では、プロパティに設定されたものはすべて、ContentControlDataContext
の直接の子になることに注意してください。ItemsSource
内のそれぞれが 内で定義されたビジュアル ツリーの であるのItemsControl
と同様です。DataContext
ItemTemplate
ここでは、OK とキャンセルのビューとビューモデルの相互作用に関して多くの詳細を隠していますが、DataTemplate が設定されている限り、ウィンドウ内にビューをレンダリングする必要があります。
アプリケーションのリソース ディクショナリでビューモデル ビュー データ テンプレートを定義しています。
<DataTemplate DataType="{x:Type SaveDocumentChangesVM}">
<SaveDocumentChangesView />
</DataTemplate>
ビューをホストするウィンドウ:
<Window x:Class="CustomDialogWindow"
SizeToContent="WidthAndHeight" ShowInTaskbar="False">
<ContentPresenter Name="DialogContentPresenter" />
</Window>
ウィンドウのコンストラクタ:
public CustomDialogWindow(object viewModel, string dialogTitle)
{
InitializeComponent();
// A datatemplate will allow WPF to figure out how to render the window contents
DialogContentPresenter.Content = viewModel;
if (dialogTitle != null)
{
Title = dialogTitle;
}
}
次のようにダイアログを表示します。
var vm = new SaveDocumentChangesVM();
var dialog = new CustomDialogWindow(vm, "This is my dialog");
dialog.ShowDialog();