Ich verwende Verhalten als angefügte Eigenschaft implementiert. Es hat zwei wesentliche Vorteile gegenüber System.Windows.Interactivity:
- es kann in Stil definiert werden.
- viel weniger XAML-Code in den
in Ihrem Fall Ansichten könnte die Ansicht wie folgt aussehen:
<UserControl ...
my:AttachedCommands.LoadedCommand="{Binding ViewLoadedCommand}">
In meiner Lösung, ich bin Befehle nicht verwenden, aber ich nenne Methoden auf Viewmodel wenn das Viewmodel IViewModelLifeCycle
Schnittstelle implementiert:
public interface IViewModelLifeCycle
{
void Activate(object extraData);
void Deactivate();
}
All meine Ansichten verwendet diesen Stil:
<Style x:Key="ViewBaseStyle">
<Setter Property="my:ViewModelLifeCycleBehavior.ActivateOnLoad" Value="True" />
und das Verhalten:
public static class ViewModelLifeCycleBehavior
{
public static readonly DependencyProperty ActivateOnLoadProperty = DependencyProperty.RegisterAttached("ActivateOnLoad", typeof (bool), typeof (ViewModelLifeCycleBehavior),
new PropertyMetadata(ActivateOnLoadPropertyChanged));
public static void SetActivateOnLoad(FrameworkElement element, bool value)
{
element.SetValue(ActivateOnLoadProperty, value);
}
public static bool GetActivateOnLoad(FrameworkElement element)
{
return (bool)element.GetValue(ActivateOnLoadProperty);
}
private static void ActivateOnLoadPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
if (DesignerProperties.GetIsInDesignMode(obj)) return;
var element = (FrameworkElement)obj;
element.Loaded -= ElementLoaded;
element.Unloaded -= ElementUnloaded;
if ((bool) args.NewValue == true)
{
element.Loaded += ElementLoaded;
element.Unloaded += ElementUnloaded;
}
}
static void ElementLoaded(object sender, RoutedEventArgs e)
{
var element = (FrameworkElement) sender;
var viewModel = (IViewModelLifeCycle) element.DataContext;
if (viewModel == null)
{
DependencyPropertyChangedEventHandler dataContextChanged = null;
dataContextChanged = (o, _e) =>
{
ElementLoaded(sender, e);
element.DataContextChanged -= dataContextChanged;
};
element.DataContextChanged += dataContextChanged;
}
else if (element.ActualHeight > 0 && element.ActualWidth > 0) //to avoid activating twice since loaded event is called twice on TabItems' subtrees
{
viewModel.Activate(null);
}
}
private static void ElementUnloaded(object sender, RoutedEventArgs e)
{
var element = (FrameworkElement)sender;
var viewModel = (IViewModelLifeCycle)element.DataContext;
viewModel.Deactivate();
}
}
TIPP: Erstellen Sie Ihre custom Item Template in Visual Studio für View und Ansichtsmodell. Es ist sehr einfach und spart viel Zeit. Die Elementvorlage kann XAML-Code mit dem Trigger/Behavior enthalten, der auf Ihren Basisstil, Ihre d:DataContext
Definition und Ihre Viewmodel-Klasse verweist.
Warum nicht mit einem Schlüssel stylen? –
@Nikita Eigentlich weiß ich nicht, wie man einen Stil erstellt, der zusammengesetzte und komplexe Anhang-Eigenschaften wie 'Interaction.Triggers' setzt. – Dai
Wo befindet sich ViewLoadedCommand? Ist das in Ihrer Sicht Modell? Sind Sie sicher, dass Sie diesen Befehl aufrufen möchten ** jedes Mal, wenn ein Benutzersteuerelement geladen wird? –