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
Merci beaucoup !! Comme vous le dites, l'événement MouseUp n'est pas capturable, PreviewMouseUp, à la place, est attrapable. J'aime ce forum. – lamarmora
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
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