2010-09-11 7 views
3

J'ai une question machiavélienne (pour moi). Dans mon application WPF, j'ai un ListBox qui a dans le ItemTemplate un Combobox. Lorsque l'utilisateur sélectionne un ComboBoxItem, je dois effectuer des opérations complexes sur ObservableCollection qui est le ItemsSource de la ListBox, puis je dois montrer le ListBox avec les données modifiées. Le problème est que si je gère l'événement "SelectionChanged" du contrôle ComboBox, chaque fois que je modifie la classe source des comboboxItems j'entre dans la méthode qui gère l'événement, et cela génère des résultats erronés. Bref je dois distinguer, d'une certaine façon, entre le SelectionChanged généré par le code, et le SelectionChanged généré manuellement par l'utilisateur avec la souris. J'ai essayé bien des égards, mais rien qui fonctionne :-(WPF distinguer entre le codage-SelectionChanged et le mouse-SelectionChanged

Le soution je pensais était le meilleur, est de gérer l'événement « GotFocus » ou « MouseUp » du ContentPresenter du ItemContainerStyle du Combo, ou bien pour gérer les mêmes événements ("GotFocus" et "MouseUp") du ItemsPanel du Combo, mais la méthode que j'ai manipulée n'a pas capturé l'événement (dans le debug le curseur n'entre pas du tout dans la méthode)

Je ne peux pas utiliser un booléen pour arrêter la méthode « SelectionChanged » jusqu'à ce que le « premier tour » est terminée, parce que les changements de la source de la classe des ComboBoxItems se produit après que la méthode a été exécuté tout.

La valeur par défaut des Combos n'est pas toujours la première (ce serait trop facile :-)), et pas toujours la même chose. Chaque fois que l'utilisateur sélectionne un élément de l'un des Combo, la valeur par défaut des autres Combos doit changer.

Pouvez-vous m'aider? Pileggi

' XAML 
<Style x:Key="modComboCriteriEventParts" TargetType="{x:Type ComboBox}"> 
    <EventSetter Event="Selector.SelectionChanged" Handler="cb_SelectionChanged"/> 
</Style> 

<DataTemplate x:Key="modLBoxCriteriParts"> 
    <ComboBox Style = "{StaticResource modComboCriteriEventParts}" 
     ItemsSource = "{Binding CriteriItemList}" 
     ItemContainerStyle = "{DynamicResource modComboContainerParts}" 
     SelectedIndex = "{Binding valueSelected}" ... /> 
</DataTemplate> 

<ListBox x:Name="lbCriteri" IsSynchronizedWithCurrentItem="True" 
    ItemsSource = "{Binding CriteriList, Source={StaticResource P_CriteriDataSource}}" 
    ItemTemplate = "{DynamicResource modLBoxCriteriParts}" 
    ... /> 


' Code Behind 
Private Sub cb_SelectionChanged(ByVal sender As System.Object, ByVal e As SelectionChangedEventArgs) 
    Dim ri as New RicambiCriteriList() As ObservableCollection(Of P_CriteriItem) 

    ' some complex operations with ri ... 

    be = BindingOperations.GetBindingExpression(Me.lbCriteri, ListBox.ItemsSourceProperty) 
    Dim allCriteri As P_Criteri = DirectCast(be.DataItem, P_Criteri) 
    allCriteri.AddData (ri) 

    e.Handled = True 
End Sub 


' Source-Class 
Public Class P_Criteri 

    Private _CriteriList As New ObservableCollection(Of P_CriteriItem) 

    Public ReadOnly Property CriteriList() As ObservableCollection(Of P_CriteriItem) 
     Get 
      CriteriList = _CriteriList 
     End Get 
    End Property 

    Public Sub AddData(ByVal CriteriListPass As ObservableCollection(Of P_CriteriItem)) 
     _CriteriList.Clear() 
     For Each a As P_CriteriItem In CriteriListPass 
      _CriteriList.Add(a) 
     Next 
    End Sub 
End Class 

Public Class P_CriteriItem 
    Implements INotifyPropertyChanged 

    Public Sub New(ByVal criterioPass As String, ByVal CriteriItemListPass As ObservableCollection(Of P_CriteriItemValore), _ 
     ByVal widthCriteriValuesPass As Double) 

     Me._criterio = criterioPass 
     Me._CriteriItemList = CriteriItemListPass 
     Me._widthCriteriValues = widthCriteriValuesPass 
    End Sub 

    Private _criterio As String = "" 
    Private _CriteriItemList As New ObservableCollection(Of P_CriteriItemValore) 

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged 

    Public Property criterio() As String 
     Get 
      Return Me._criterio 
     End Get 
     Set(ByVal value As String) 
      If Not Object.Equals(Me._criterio, value) Then 
       Me._criterio = value 
       Me.OnPropertyChanged ("criterio") 
      End If 
     End Set 
    End Property 

    Public Property CriteriItemList() As ObservableCollection(Of P_CriteriItemValore) 
     Get 
      Return Me._CriteriItemList 
     End Get 
     Set(ByVal value As ObservableCollection(Of P_CriteriItemValore)) 
      If Not Object.Equals(Me._CriteriItemList, value) Then 
       Me._CriteriItemList = value 
       Me.OnPropertyChanged ("CriteriItemList") 
      End If 
     End Set 
    End Property 

    Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String) 
     Dim handler As PropertyChangedEventHandler = Me.PropertyChangedEvent 
     If handler IsNot Nothing Then 
      RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
     End If 
    End Sub 
End Class 

Public Class P_CriteriItemValore 
    Implements INotifyPropertyChanged 

    Public Sub New(ByVal criterioValorePass As String) 
     Me._criterioValore = criterioValorePass 
    End Sub 

    Private _criterioValore As String = Nothing 

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged 

    Public Property criterioValore() As String 
     Get 
      Return Me._criterioValore 
     End Get 
     Set(ByVal value As String) 
      If Not Object.Equals(Me._criterioValore, value) Then 
       Me._criterioValore = value 
       Me.OnPropertyChanged ("criterioValore") 
      End If 
     End Set 
    End Property 

    Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String) 
     Dim handler As PropertyChangedEventHandler = Me.PropertyChangedEvent 
     If handler IsNot Nothing Then 
      RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
     End If 
    End Sub 
End Class 

Répondre

4

Tout d'abord, je pense qu'il est préférable de gérer les événements sur le conteneur de l'élément lui-même et non sur le présentateur de contenu dans l'élément. Et maintenant que je pense à cela, c'est probablement pourquoi vous ne voyez pas les événements. Le conteneur est probablement en train de manger les événements pour la sélection.

Mais de toute façon, si vous ne pouvez pas attraper les événements MouseDown/GotFocus, vous pouvez utiliser les événements PreviewMouseDown/PreviewGotFocus. Juste au cas où vous n'êtes pas sûr de ce que cela signifie, vous devriez lire sur l'architecture de routage d'événements wpf et les événements de bulles et de tunnellisation.

+2

Merci beaucoup !! Comme vous le dites, l'événement MouseUp n'est pas capturable, PreviewMouseUp, à la place, est attrapable. J'aime ce forum. – lamarmora

+0

A eu un problème similaire. Je voulais montrer des informations de courrier électronique (to, cc, subject, message) en utilisant un élément de grille ListView connecté à 'EmailTableA'. Cliquez sur cet élément pour remplir une liste déroulante avec son titre et les autres zones de texte basées sur cet élément de 'EmailTableA'. Si je cliquais sur la liste déroulante pour changer le titre, j'obtiendrais plutôt l'information basée sur ce titre de courriel, 'EmailTableB', une autre que celle utilisée par la grille. Le problème était que si je cliquais sur l'élément ListView, au lieu d'afficher l'élément de 'EmailTableA', il utilisait l'événement' SelectedChanged' du dropdown et le montrait depuis 'EmailTableB'. – vapcguy

+0

J'ai résolu le problème tout comme lamarmora suggéré - j'ai changé mon événement dropdown de 'SelectedChanged' en' PreviewMouseUp'. Ensuite, mon ListView a rempli les données de 'EmailTableA' et n'a plus exécuté mon événement sur ma liste déroulante et n'a plus saisi les données' EmailTableB' sans être appelé directement à partir de mes clics de souris. Si je cliquais sur la liste déroulante pour récupérer un e-mail différent, il l'a saisi à partir de "EmailTableB", comme souhaité. – vapcguy