3

マキャベリ的な質問があります(私にとって)。私の WPF アプリケーションには、ItemTemplate に Combobox を持つ ListBox があります。ユーザーが ComboBoxItem を選択すると、ListBox の ItemsSource である ObservableCollection に対していくつかの複雑な操作を行う必要があります。次に、変更されたデータで ListBox を表示する必要があります。問題は、ComboBox コントロールのイベント「SelectionChanged」を処理すると、イベントを処理するメソッドに入力するコンボボックス項目のソース クラスを変更するたびに、間違った結果が生成されることです。つまり、コードによって生成された SelectionChanged と、ユーザーがマウスで手動で生成した SelectionChanged を何らかの方法で区別する必要があります。私は多くの方法を試しましたが、うまくいきません:-(

私が最善だと思った解決策は、Combo の ItemContainerStyle の ContentPresenter のイベント「GotFocus」または「MouseUp」を処理するか、または ItemsPanel の同じイベント (「GotFocus」および「MouseUp」) を処理することです。コンボですが、私が処理したメソッドはイベントをキャプチャしませんでした(デバッグでは、カーソルはメソッドにまったく入りません)。

メソッドがすべて実行された後に ComboBoxItems のソースクラスの変更が発生するため、「最初のラウンド」が終了するまでブール値を使用してメソッド「SelectionChanged」を停止することはできません。

Combos のデフォルト値は常に最初であるとは限りません (簡単すぎるでしょう :-))、常に同じであるとは限りません。ユーザーがいずれかのコンボのアイテムを選択するたびに、他のコンボのデフォルト値を変更する必要があります。

手伝って頂けますか?ピレッジ

' 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
4

1 に答える 1

4

まず、アイテム内のコンテンツ プレゼンターではなく、アイテム コンテナー自体でイベントを処理する方がよいと思います。考えてみれば、それがおそらくイベントが表示されない理由です。コンテナーは、選択のためにイベントを食べている可能性があります。

いずれにしても、MouseDown/GotFocus イベントをキャッチできない場合は、PreviewMouseDown/PreviewGotFocus イベントを使用できます。これらが何を意味するのかわからない場合に備えて、wpf イベントルーティングアーキテクチャとバブリングおよびトンネリングイベントを読む必要があります。

于 2010-09-12T10:04:20.800 に答える