2016-10-11 7 views
0

Situation: Dans le modèle MVVM, j'ai des liaisons d'entrée dans une liste qui ne fonctionne que lorsque la liste est mise au point. Cependant, chaque fois que l'utilisateur clique, la liste est floue et l'utilisateur ne peut pas exécuter les liaisons d'entrée.Impossible de se concentrer ListView

Problème: Je souhaite mettre l'accent sur la liste (sur un clic de bouton) de telle sorte que les liaisons d'entrée fonctionnent. Ce que j'ai essayé: J'ai essayé d'utiliser la propriété jointe IsFocused (où je me concentre en utilisant UIElement.Focus() et/ou Keyboard.Focus()) et en le liant à une variable bool dans le ViewModel que je définirais en utilisant un Je commande.

J'ai également essayé un exemple séparé où je peux utiliser la méthode System.Windows.Input.Keyboard.Focus (item) dans le code derrière (je veux dire le fichier .xaml.cs avec le même nom) pour focaliser la liste et il fonctionne! Mais, je ne sais pas comment implémenter la chose similaire dans un ViewModel qui est connecté en utilisant un attribut d: DesignInstance.

Je crois que l'événement mouseclick est barboté et géré ailleurs, ce qui provoque la mise au point de la liste dès que je clique dessus. Par exemple, si je trouve un moyen de définir l'événement comme manipulé, cela aidera, mais encore une fois, je ne sais pas comment le faire dans un viewmodel. Voici ma propriété ci-joint:

FocusExtension.cs

public static class FocusExtension { 
    public static bool GetIsFocused(DependencyObject obj) { 
     return (bool)obj.GetValue(IsFocusedProperty); 
    } 

    public static void SetIsFocused(DependencyObject obj, bool value) { 
     obj.SetValue(IsFocusedProperty, value); 
    } 

    public static readonly DependencyProperty IsFocusedProperty = 
     DependencyProperty.RegisterAttached(
      "IsFocused", typeof(bool), typeof(FocusExtension), 
      new UIPropertyMetadata(false, OnIsFocusedPropertyChanged)); 

    private static void OnIsFocusedPropertyChanged(
     DependencyObject d, 
     DependencyPropertyChangedEventArgs e) { 
     var uie = (UIElement)d; 
     if ((bool)e.NewValue) { 
      uie.Focus(); 
     } 
    } 
} 

XAML fichier:

<ListView 
     x:Name="lv" 
     Grid.Column="2" Margin="2" MinWidth="250" Height="400" ToolTip="the List" 
     HorizontalContentAlignment="Stretch" 
     ItemsSource="{Binding ListBindingInVM}" 
     ScrollViewer.HorizontalScrollBarVisibility="Auto" 
     ScrollViewer.CanContentScroll="False" 
     dd:DragDrop.IsDragSource="True" 
     dd:DragDrop.IsDropTarget="True" 
     dd:DragDrop.DropHandler="{Binding }" 
     behaviour:ListViewAutoScroll.AutoScrollToEnd="True" 
     ScrollViewer.VerticalScrollBarVisibility="Visible" 
     > 

     <ListView.Style> 
      <Style TargetType="ListView" > 
       <Setter Property="ViewModels:FocusExtension.IsFocused" Value="{Binding ListFocused, Mode=TwoWay}"></Setter> 
       <!--The one below is not clean, but worked. However, list goes out of focus on click. --> 
       <Style.Triggers> 
        <Trigger Property="IsMouseOver" Value="True"> 
         <Setter Property="ViewModels:FocusExtension.IsFocused" Value="True"></Setter> 
        </Trigger> 
       </Style.Triggers> 


      </Style> 
     </ListView.Style> 

     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="MouseDown"> 
      <!--This command sets the ListFocused to true--> 
       <i:InvokeCommandAction Command="{Binding BringListToFocus }"></i:InvokeCommandAction> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 


     <ListView.InputBindings> 
      <!-- Bindings that don't work when list is not focused--> 
      <KeyBinding Modifiers="Control" Key="C" Command="{Binding CopyCommand}"/> 
      <KeyBinding Modifiers="Control" Key="V" Command="{Binding PasteCommand}"/> 
     </ListView.InputBindings> 

     <ListView.ContextMenu> 
      <ContextMenu> 
       <MenuItem Header="Copy" Command= "{Binding CopyCommand}"></MenuItem> 
       <MenuItem Header="Paste" Command= "{Binding PasteCommand}"></MenuItem> 
      </ContextMenu> 
     </ListView.ContextMenu> 
+2

MVVM! = Pas de code derrière. Cela signifie ne pas avoir de code spécifique à l'interface utilisateur dans vos modèles de vue. Essayer de mettre l'accent dans votre machine virtuelle n'est pas la meilleure idée, comme vous l'avez constaté. Côté note, si vous rencontrez des problèmes avec les événements, prenez Snoop. Il va suivre les événements et vous dire quel élément bloque le bouillonnement. – Will

+0

Merci pour le commentaire :) Je sais, mais les "directives" sur lesquelles je travaille veulent que je ne mette pas de code dans le code-behind. Pour utiliser Snoop sera long processus, parler aux membres de l'équipe et d'autres choses. Est-il possible d'avoir une solution de contournement avec n'importe quel changement dans seulement le xaml et/ou peut-être le viewmodel? – 10101010

+1

Repoussez les directives.Et Snoop n'est pas un "long processus", c'est une application qui vous montre ce qui se passe dans votre interface utilisateur WPF, y compris les erreurs de liaison, la propagation d'événements et autres goodies. C'est un outil génial et gratuit. – Will

Répondre

-1

Le comportement de mise au point que vous décrivez est facilement mis en œuvre à partir du codebehind, et cela ne crée viole pas la Modèle MVVM. Considérez le poste de Josh Smith, ci-dessous:

https://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090097

L'utilisation d'un ViewModel ici rend beaucoup plus facile de créer une vue qui peut afficher un objet client et permettre des choses comme un état « non sélectionné » d'une propriété booléenne. Il fournit également la capacité de dire facilement au client de sauvegarder son état. Si la vue était liée directement à un objet client, la vue nécessiterait beaucoup de code pour pour que cela fonctionne correctement. Dans une architecture MVVM bien conçue, le codebehind de la plupart des vues doit être vide ou, tout au plus, contenir uniquement du code qui manipule les contrôles et les ressources contenus dans cette vue . Parfois, il est également nécessaire d'écrire du code dans un code viewbehind View qui interagit avec un objet ViewModel, tel que l'accrochage d'un événement ou l'appel d'une méthode qui serait autrement très difficile à invoquer à partir du ViewModel lui-même.