2014-06-19 3 views
1

Je développe un projet afin de manipuler beaucoup d'objets avec plusieurs modalités (souris, leapmotion, touch ...). Je l'ai fait en utilisant le modèle MVVM donc j'ai plusieurs Views et ViewModels pour tous les composants que j'utiliserai. Pour le rendre plus facile à développer, j'ai choisi d'avoir un composant Canvas dans lequel je vais manipuler les Grids. Chaque Grille peut contenir n'importe quel type d'objet (Forme, Texte, Image, Documents ...). Pour pouvoir avoir toutes les modalités liées à ma méthode, j'ai décidé de construire un écouteur par modalité (1 pour la souris, 1 pour la leapmotion ...) et de leur faire détecter les gestes de base (comme Click, DoubleClick. ..). Tous les gestes que j'ai choisi de détecter sont associés à une méthode via un dictionnaire. Quoi qu'il en soit, la liaison fonctionne comme prévu puisqu'elle exécute la bonne méthode. T o donner un exemple, j'ai l'action d'appeler dans mon écouteur de souris:InvalidOperationException, le thread appelant doit être STA car

if (_leftClickCounter == 1 && _capturedLeft == false) 
{ 
    if (_dic.ContainsKey(Key.OnClick)) 
    { 
     Action<object> action = _dic[Key.OnClick]; 
     action.Invoke(null); 
    } 
} 

Où:

  • _dic est mon dictionnaire
  • clé une énumération des gestes (comme OnClick, OnDoubleClick ...)
  • l'action de la méthode pour exécuter

Dans mon exemple, la méthode est exécutée:

public void Add(object sender) 
{ 
    ObjectModel objectModel = new ObjectModel(); 
    ObjectView objectView = new ObjectView(objectModel); 
    this.objectViews.Add(objectView); 
} 

Lorsque l'expéditeur est simplement utilisé à des fins de test. Il reste inutilisé dans la méthode. Mon exécution s'arrête quand il essaie d'instancier mon ObjectView en disant:

InvalidOperationException 
The calling thread must be STA, because many UI components require this 

classe Mon ObjectView.xaml.cs est:

public partial class ObjectView : UserControl 
{ 
    public ObjectView(ObjectModel obj) 
    { 
     InitializeComponent(); 

     EventLinker linker = new EventLinker(this.visualBox); 
     ObjectViewModel objectVM = new ObjectViewModel(obj, linker); 
     this.DataContext = objectVM; 
    } 
} 

Et son ObjectView.xaml définissant le UserControl à utiliser est très basique:

<UserControl x:Class="AusyTouchMultimodal_v1.View.ObjectView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="300"> 

    <Grid x:Name="visualBox" Background="Blue"/> 

</UserControl> 

Je n'ai aucune erreur de compilation, juste cette InvalidOperationException. Quelqu'un peut-il m'expliquer ce problème?

Merci!

Répondre

2

Essayez d'appeler vos actions en fil ui, comme celui-ci

if (_leftClickCounter == 1 && _capturedLeft == false) 
{ 
    if (_dic.ContainsKey(Key.OnClick)) 
    { 
     Action<object> action = _dic[Key.OnClick]; 
     // action.Invoke(null);   
     System.Windows.Application.Current.Dispatcher.BeginInvoke(call your action) 
    } 
} 
+0

cela fonctionne bien. mais pourquoi mon application ne peut pas être exécutée par un seul fil si je ne spécifie pas d'autres? – baptiste

+0

Je pense que d'autres threads sont réellement utilisés. Mais vos contrôles sont dans la portée du thread ui donc toute modification que vous essayez de faire sur ui (y compris les propriétés qui ont été limitées avec viewmodel) devrait être fait en invoquant l'action sur ui thread. –

Questions connexes