В WPF различают coding-SelectionChanged и mouse-SelectionChanged

У меня есть макиавеллиевский вопрос (для меня). В моем приложении WPF у меня есть ListBox, который содержит в ItemTemplate Combobox. Когда пользователь выбирает ComboBoxItem, я должен выполнить некоторые сложные операции с ObservableCollection, которая является ItemsSource ListBox, затем я должен показать ListBox с измененными данными. Проблема заключается в том, что если я обрабатываю событие "SelectionChanged" элемента управления ComboBox, каждый раз, когда я изменяю исходный класс элементов comboboxItems, которые я ввожу в метод, который обрабатывает событие, это приводит к неверным результатам. Короче говоря, я должен каким-то образом различать SelectionChanged, сгенерированный кодом, и SelectionChanged, сгенерированный вручную с помощью мыши. Я пробовал много способов, но ничего, что работает:-(

Я решил, что лучшим решением будет обработать событие "GotFocus" или "MouseUp" ContentPresenter ItemContainerStyle в Combo или обработать те же события ("GotFocus" и "MouseUp") ItemsPanel Комбо, но метод, который я обработал, не захватил событие (при отладке курсор вообще не входит в метод).

Я не могу использовать логическое значение, чтобы остановить метод "SelectionChanged" до тех пор, пока "первый раунд" не будет завершен, потому что изменения в классе-источнике ComboBoxItems происходят после того, как метод был полностью выполнен.

Значение по умолчанию для Combos не всегда первое (это было бы слишком просто:-)) и не всегда одно и то же. Каждый раз, когда пользователь выбирает элемент одной из комбинаций, значение других комбинаций по умолчанию должно меняться.

Вы можете мне помочь? 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

1 ответ

Решение

Во-первых, я думаю, что лучше обрабатывать события в самом контейнере элемента, а не в представителе содержимого в элементе. И теперь, когда я думаю об этом, возможно, поэтому вы не видите события. Контейнер, вероятно, ест события для выбора.

Но в любом случае, если вы не можете перехватить события MouseDown/GotFocus, вы можете использовать события PreviewMouseDown/PreviewGotFocus. На всякий случай, если вы не уверены, что это значит, вы должны прочитать об архитектуре маршрутизации событий wpf, а также событиях пузырькового и туннельного потоков.

Другие вопросы по тегам