Uso comportamento implementato come proprietà associata. Ha due importanti vantaggi rispetto a System.Windows.Interactivity:
- può essere definito con stile.
- molto meno codice XAML in vista
nel tuo caso, la vista potrebbe apparire come:
<UserControl ...
my:AttachedCommands.LoadedCommand="{Binding ViewLoadedCommand}">
Nella mia soluzione, non sto usando i comandi, ma chiamare metodi su ViewModel se il ViewModel implementa IViewModelLifeCycle
interfaccia:
public interface IViewModelLifeCycle
{
void Activate(object extraData);
void Deactivate();
}
Tutti i miei punti di vista utilizza questo stile:
0.123.
<Style x:Key="ViewBaseStyle">
<Setter Property="my:ViewModelLifeCycleBehavior.ActivateOnLoad" Value="True" />
e il comportamento:
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();
}
}
SUGGERIMENTO: Creare la custom Item Template in Visual Studio per View e ViewModel. è molto facile e consente di risparmiare un sacco di tempo. Il modello dell'articolo può contenere codice xaml con trigger/comportamento, che punta allo stile di base, alla definizione d:DataContext
e alla classe viewmodel.
Perché non stile con una chiave? –
@Nikita In realtà, non so come creare uno stile che imposta proprietà composite e complesse come "Interaction.Triggers". – Dai
Dove si trova ViewLoadedCommand? Questo è nel tuo modello di vista? Sei sicuro di voler chiamare questo comando ** ogni volta ** viene caricato un controllo utente? –