В WPF различают coding-SelectionChanged и mouse-SelectionChanged - PullRequest
3 голосов
/ 12 сентября 2010

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

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

Я не могу использовать логическое значение, чтобы остановить метод «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 Ответ

4 голосов
/ 12 сентября 2010

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

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

...