2010-12-29 10 views
5

Tengo PreviewMouseDown evento en TreeView para determinar si el usuario puede seleccionar otro elemento en función de alguna lógica. Si los datos actuales del artículo cambiaron, aparecerá MessageBox que le pregunta al usuario si desea descartar los cambios. si el usuario presiona SÍ, configuro e.Handled = false; para habilitar la nueva selección. y si el usuario presiona NO, configuro e.Handled = true; para cancelar la nueva selección.¿Wpf detiene el evento de enrutamiento cuando aparece MessageBox?

El problema es que aunque configuré e.Handled = false, el evento se detiene y no ocurre ningún evento de selección en TreeView. Alguien tiene una solución para eso?

¡Gracias de antemano!

Respuesta

3

El cambio de foco en el cuadro de mensaje cancela el evento de abajo del mouse por lo que no importa si se maneja o no. Como sabe qué elemento el usuario estaba intentando seleccionar antes de mostrar el cuadro de mensaje, simplemente seleccione ese elemento programáticamente si el usuario presiona SÍ.

+0

Pero no sé qué elemento el usuario estaba tratando de seleccionar. Solo tengo MouseEventArgs. ¿Alguna idea de cómo obtener este artículo o debería registrarme en SelectedItemChanged? – yossharel

+1

Utilice esta técnica para obtener el DataContext: http://stackoverflow.com/questions/1092639/in-wpf-how-do-i-get-the-data-object-associated-to-the-tree-view-item -bajo y luego use SelectedItems.Add() –

+0

MouseEventArgs.Source le indica el objeto sobre el que se hizo clic. Estaba haciendo algo similar con TabItems (que muestra un cuadro de diálogo cuando el usuario seleccionaba una pestaña diferente), y la solución era establecer myTabControl.SelectedItem = e.Source. – TarkaDaal

1

Me doy cuenta de que esta es una vieja pregunta, pero pensé que agregaría mi respuesta.

En realidad, @yossharel, SÍ sabes qué artículo el usuario estaba tratando de seleccionar, de MouseEventArgs. Necesitas mirar e.OriginalSource (probablemente un TextBlock), que es en lo que el usuario hizo clic. Como tal, tiene un DataContext.

Por lo tanto, establezca SelectedItem TreeView igual a e.OriginalSource.DataContext.

En VB, puede ser explícita o implícita: myTreeView.SelectedItem = CType (e.OriginalSource, TextBlock) .DataContext() myTreeView.SelectedItem = e.OriginalSource.DataContext()

En C#, Deberá determinar el tipo de e.OriginalSource. Haga esto poniendo un punto de quiebre y vea lo que Studio le dice que es. En este ejemplo: myTreeView.SelectedItem = ((TextBlock) e.OriginalSource) .DataContext()

Aquí hay un ejemplo de mi propio código. En mi caso, es un DataGrid en lugar de un TreeView, pero debería funcionar igual. Uso este código para avisar al usuario si hay cambios no guardados en el elemento seleccionado. Si el usuario responde "Sí" a "Continuar sin guardar?" el código continúa con la nueva selección. De lo contrario, dejo que el cuadro de mensaje bloquee el evento RoutedEvent, impidiendo que se active el evento SelectionChanged.

Private Sub dgDataGrid_PreviewMouseLeftButtonDown(sender As Object, e As System.Windows.Input.MouseButtonEventArgs) Handles dgDataGrid.PreviewMouseLeftButtonDown 
    If dgDataGrid.SelectedItem IsNot Nothing Then 
     If MyDataContext.ExternalViewModel.ItemIsModified Then 
      Dim prompt As String = String.Format("Changes have not been saved.{0}{0}Continue without saving?", vbCrLf) 
      Dim title As String = "Changes Not Saved" 
      Dim result As MsgBoxResult = MsgBox(prompt, MsgBoxStyle.Exclamation Or MsgBoxStyle.YesNo, title) 
      If result = MsgBoxResult.Yes Then 
       dgDataGrid.SelectedItem = e.OriginalSource.DataContext() 
      End If 
     End If 
    End If 
End Sub 

Private Sub dgDataGrid_SelectionChanged(sender As System.Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles dgDataGrid.SelectionChanged 
    MyDataContext.SetSearchItem(dgDataGrid.SelectedItem) 
End Sub 
Cuestiones relacionadas