Beschreibung:
Hallo zusammen,
ich weiss nicht wofür das im MVVM nützlich sein sollte da man ja eigentlich alles mittels Bindings lösen kann, aber dennoch Poste ich mal eine Möglichkeit um einen Command mittels Event auszulösen
Wichtig ist dass vorher das Blend SDK für Silverlight Heruntergeladen und Installiert wird.
Ein Verweis auf die System.Windows.Interactivity (zu finden unter C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\Silverlight\v4.0\Libraries) hinzugefügt wird
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity;
using System.Reflection;
using System.Linq;
namespace EventToCommand
{
public class EventToCommandCore : TriggerAction<DependencyObject>
{
#region DelegateCommands
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register( "CommandParameter", typeof( object ), typeof( EventToCommandCore ), null );
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register( "Command", typeof( ICommand ), typeof( EventToCommandCore ), null );
public static readonly DependencyProperty InvokeParameterProperty =
DependencyProperty.Register( "InvokeParameter", typeof( object ), typeof( EventToCommandCore ), null );
#endregion
#region Properties And Fields
public object InvokeParameter
{
get { return this.GetValue( InvokeParameterProperty ); }
set { this.SetValue( InvokeParameterProperty, value ); }
}
public ICommand Command
{
get { return (ICommand)this.GetValue( CommandProperty ); }
set { this.SetValue( CommandProperty, value ); }
}
public string CommandName{get; set;}
public object CommandParameter
{
get { return this.GetValue( CommandParameterProperty ); }
set { this.SetValue( CommandParameterProperty, value ); }
}
#endregion
#region methods
protected override void Invoke( object parameter )
{
this.InvokeParameter = parameter;
if ( this.AssociatedObject != null )
{
ICommand Command = this.ResolveCommand();
if ( Command != null && Command.CanExecute( this.CommandParameter ) )
{
Command.Execute( this.CommandParameter );
}
}
}
private ICommand ResolveCommand()
{
ICommand command = null;
if ( this.Command != null )
{
return this.Command;
}
var frmElement = (FrameworkElement)this.AssociatedObject;
if ( frmElement != null )
{
object dtContext = frmElement.DataContext;
if ( dtContext != null )
{
PropertyInfo cmdPropertyInfo = dtContext.GetType().GetProperties( BindingFlags.Public | BindingFlags.Instance ).
FirstOrDefault(
c =>
typeof( ICommand ).IsAssignableFrom( c.PropertyType ) &&
string.Equals( c.Name, this.CommandName, StringComparison.Ordinal )
);
if ( cmdPropertyInfo != null )
{
command = (ICommand)cmdPropertyInfo.GetValue( dtContext, null );
}
}
}
return command;
}
#endregion
}
}
Das ganze kann dann folgendermaßen verwendet werden
<UserControl x:Class="DemoApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:EventToCommand"
xmlns:VM="clr-namespace:DemoApp.ViewModel"
>
<UserControl.Resources>
<VM:DemoAppViewModel x:Key="DAVM" />
</UserControl.Resources>
<StackPanel x:Name="LayoutRoot" Background="White" DataContext="{StaticResource DAVM}">
<sdk:DatePicker Name="DatePickerControl"
Margin="5"
SelectedDateFormat="Short"
IsDropDownOpen="False"
SelectedDate="{Binding Path=DatePickerProperty, Mode=TwoWay}"
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedDateChanged">
<cmd:EventToCommandCore Command="{Binding Path=SelectionChangedCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=InvokeParameter}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</sdk:DatePicker>
</StackPanel>
Im ViewModel könnte es dann Folgendermaßen aussehen:
(Nur Methoden definition)
private void SelectionChangedExecute( object state )
{
if ( state is SelectionChangedEventArgs )
{
//Do Some Stuff
}
}
Wie gesagt ich habe keine Ahnung wofür man das brauchen sollte...
Schlagwörter: Event, Command, Silverlight
MfG
ProGamer*Der Sinn Des Lebens Ist Es, Den Sinn Des Lebens Zu Finden!
*"Wenn Unrecht zu Recht wird dann wird Widerstand zur Pflicht."
*"Ignorance simplifies ANY problem."
*"Stoppt die Piraterie der Musikindustrie"
Ich finds ja lustig, dass du keine Ahnung hast wie man das brauchen, aber man kann das z.B. gut für das Loaded Event brauchen und dann Daten laden bzw. neu laden.
ImageTools for Silverlight: http://imagetools.codeplex.com | http://www.silverdiagram.net | http://www.cleancodedeveloper.de b:::
Wie gesagt ich habe keine Ahnung wofür man das brauchen sollte...
Wieso machst du dir dann die Mühe so etwas zu programmieren?
Soetwas, ebenfalls "EventToCommand" benannt existiert schon im MVVM Light Toolkit von Codeplex ^^
@malignate: danke für die Verwendungsmöglichkeit ^^
@iced-t89: Wie gesagt ich weiss nicht wofür man es gebrauchen kann da ja sogut wie alles über Bindings möglich ist.
Als ich mir den Code zusammengesucht hatte brauchte ich eine möglichkeit um vom DatePicker das CalendarClosed-Event im ViewModel zu verarbeiten. Mittlerweile ist dafür ein Converter im Einsatz.
MfG
ProGamer*Der Sinn Des Lebens Ist Es, Den Sinn Des Lebens Zu Finden!
*"Wenn Unrecht zu Recht wird dann wird Widerstand zur Pflicht."
*"Ignorance simplifies ANY problem."
*"Stoppt die Piraterie der Musikindustrie"
Das MVVM-"Pattern" kam leider erst nach der Entwicklung der WPF(/E) auf.
Sinn und Zweck des MVVM-"Patterns" ist die Entkopplung von Logik und UI, inkl. Testbarkeit der Logik mittels Unittests. (Wie bei richtigen Patterns auch.)
Databinding ist dort an sich ok, wenn man die Logik des ButtenClick nicht in Codebehinddatei abhandelt, sondern als Aktion betrachtet die an den Controller(Viewmodell) weitergeleitet wird.
In der WPF(/E) wurden leider Routet Events und ähnliche Scheusslichkeiten eingeführt die dieser Trennung entgegenwirken. Jedoch gibt es Workarounds...
MVVM is alles andere als Perfekt und wird wohl irgendwann durch das gute MVC ersetzt, wie bei ASP.Net(Da gab es auch erst ein propagiertes Ersatz"pattern")...
Natürlich geht MVC immer... - Besser jedoch mit Unterstützung der IDE und Herstellerenthusiasmus.