2011-06-27 6 views
4

Comment lier un événement CLR à l'aide du modèle mvvm?Liaison MVVM aux événements CLR

Pour les événements routés, j'utilise EventToCommandTrigger de la structure de Cinch et cela fonctionne très bien.

J'ai extrait le Behaviors and Effects des Expression Blend Samples et il semble que DataEventTrigger soit ce que je devrais utiliser, mais l'exemple est un peu déroutant.

Je souhaite que l'événement IsVisibleChanged déclenche mon IsVisibleChangedCommand. Je ne suis pas sûr non plus quel code doit aller dans le ViewModel pour soutenir ceci.

<i:Interaction.Triggers> 

    <i:EventTrigger EventName="SelectedItemChanged"> 
     <framework:EventToCommandTrigger Command="{Binding SelectedMenuItemChangedCommand}" 
             CommandParameter="{Binding SelectedValue, ElementName=lstClusters}" /> 
    </i:EventTrigger> 

    <framework:DataEventTrigger EventName="IsVisibleChanged" 
          Source="{Binding IsVisibleChangedCommand}"> 
    </framework:DataEventTrigger> 

</i:Interaction.Triggers> 

Répondre

7

Vous pouvez utiliser l'expression SDK Blend pour appeler les commandes en réponse à des événements en général, mais mon expérience a été que tous les événements ne sont pas pris en charge par EventTrigger.

Par exemple, cela semble fonctionner:

<Label Content="LabelText"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="MouseMove"> 
      <i:InvokeCommandAction Command="{Binding IsVisibleChangedCommand, Mode=OneWay}"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</Label> 

Mais cela ne veut pas:

<Label Content="LabelText"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="IsVisibleChanged"> 
      <i:InvokeCommandAction Command="{Binding IsVisibleChangedCommand, Mode=OneWay}"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</Label> 

Je ne sais pas pourquoi, mais Blend SDK ne semble pas que la propriété IsVisible . Vous pouvez faire quelque chose de similaire, mais en utilisant la visibilité (au lieu de IsVisible) avec un PropertyChangedTrigger comme celui-ci:

<Label x:Name="label1" Content="LabelText"> 
    <i:Interaction.Triggers> 
     <ei:PropertyChangedTrigger Binding="{Binding Visibility, ElementName=label1}"> 
      <i:InvokeCommandAction Command="{Binding IsVisibleChangedCommand, Mode=OneWay}"/> 
     </ei:PropertyChangedTrigger> 
    </i:Interaction.Triggers> 
</Label> 

BTW - Voici les espaces de noms:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 

De plus, voici une autre solution à votre problème spécifique Au lieu de lier directement un événement à une commande, vous pouvez lier la propriété Visibility de votre objet à une propriété viewmodel et exécuter la commande à partir de l'accesseur de propriété, comme suit:

Vue:

<UserControl x:Class="SampleApp.Views.EventBindingDemoView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      Height="200" Width="200"> 
    <UserControl.Resources> 
     <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 
    </UserControl.Resources> 
    <Grid> 
     <Label Content="LabelText" Visibility="{Binding Path=ElementIsVisible, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}}"/> 

     <!-- The rest of your view here --> 

    </Grid> 
</UserControl> 

ViewModel (ViewModelBase devrait mettre en œuvre INotifyPropertyChanged et OnPropertyChanged (string propertyName)):

public class EventBindingDemoViewModel : ViewModelBase 
{ 
    private bool ElementIsVisibleField = true; // or false if it should initially be hidden 
    public bool ElementIsVisible 
    { 
     get { return this.ElementIsVisibleField; } 
     set 
     { 
      if (this.ElementIsVisibleField != value) 
      { 
       this.ElementIsVisibleField = value; 
       this.OnPropertyChanged("ElementIsVisible"); 

       // Execute command 
       this.IsVisibleChangedCommand.Execute(null); 
      } 
     } 
    } 

    public ICommand IsVisibleChangedCommand; 

    // The rest of your viewmodel here 
} 

De toute façon devrait fonctionner.

+0

Mystère résolu! IsVisibleChanged est un événement CLR, pas un événement routé. Le Blend SDK EventTrigger ne fonctionne qu'avec les événements routés. –

+0

La balise récapitulative sur DataEventTrigger indique «Déclenchement qui se déclenche lorsqu'un événement ** CLR est déclenché ** sur un objet peut être utilisé pour déclencher des événements sur le contexte de données, par opposition à un EventTrigger standard qui utilise des événements routés sur FrameworkElements. " Peut-être que je vais poster un message sur leur forum de discussion à ce sujet. – kevin

+2

Notez que IsVisible et Visibility ne sont pas nécessairement la même chose: "La détermination de la valeur IsVisible tient compte de tous les facteurs de la disposition.En revanche, Visibility, qui est une propriété réglable, indique seulement l'intention de rendre visible un élément ou invisible." – Gusdor