Die Steuerung eines ChildWindow-Objektes in Silverlight wirft sehr schnell Fragen auf, wenn MVVM sauber eingesetzt werden soll. Wann ist die Eigenschaft DialogResult zu setzen und wer ist dafür verantwortlich, sind die ersten Fragen, die sich stellen.
Ansatz 1: Binding auf Eigenschaft DialogResult
Der erste Versuch liegt vermutlich darin, die Eigenschaft DialogResult des ChildWindow auf eine Eigenschaft des dahinter liegenden ViewModels zu binden. Dies wird jedoch fehl schlagen, da es sich dabei nicht um eine Dependency Property handelt. Ein Binding ist also nicht möglich. Dieser Weg scheitert hier. Eine Beschreibung dieser Eigenschaft findet sich im MSDN.
Ansatz 2: Attached Behavior
Eine funktionierende Lösung besteht darin, ein Attached Behavior zu implementieren. Dieses stellt eine Dependency Property zur Verfügung, welche auf einem ChildWindow an das dahinter liegende ViewModel gebunden werden kann. Das ViewModel selbst muss dafür eine entsprechende Eigenschaft zur Verfügung stellen.
public class DialogResultBehavior
{
public static readonly DependencyProperty DialogResultProperty =
DependencyProperty.RegisterAttached(
"DialogResult", typeof(bool?), typeof(DialogResultBehavior),
new PropertyMetadata(DialogResultPropertyChanged)
);
private static void DialogResultPropertyChanged(
DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e)
{
var childWindow = dependencyObject as ChildWindow;
if (childWindow != null)
childWindow.DialogResult = e.NewValue as bool?;
}
public static bool? GetDialogResult(ChildWindow childWindow)
{
return childWindow.GetValue(DialogResultProperty) as bool?;
}
public static void SetDialogResult(ChildWindow childWindow, bool? value)
{
childWindow.SetValue(DialogResultProperty, value);
}
}
Eingebunden wird dies im ChildWindow nun folgendermaßen:
<controls:ChildWindow x:Class="DevTyr.ChildWindow.MvvmDemo.Views.DateSelectionWindow"
xmlns="schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="schemas.microsoft.com/winfx/2006/xaml"
xmlns:beh="clr-namespace:DevTyr.ChildWindow.MvvmDemo.Behaviors"
beh:DialogResultBehavior.DialogResult="{Binding DialogResult}">
// Markup
</controls:ChildWindow>
In dieser Definition wird vorausgesetzt, dass das ViewModel eine Eigenschaft DialogResult bereit stellt. Diese wird durch das ViewModel mit dem korrekten Wert gesetzt. Im Normalfall geschieht dies durch an Schaltflächen gebundene Commands.
Das Ergebnis ist nun ein sauberer Weg, ein ChildWindow durch das im ViewModel implementierte Verhalten zu steuern. Wege á la Ereignishandler für das Click-Event, welche das MVVM-Pattern brechen, werden dadurch vermieden.
Hallo Norbert,
genau so eine Hilfestellung wie hier habe ich verzweifelt gesucht. Allerdings ist mir nicht ganz klar wie ich nun in meinem ViewModel mit dem DialogResult arbeite. Kannst du evtl. deinen Artikel noch etwas erweitern bzw. ausführen?
LG