/// <summary> /// Based on the solution proposed here: /// Source: http://stackoverflow.com/questions/20244916/wpf-treeview-selection-change /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void uiElement_PreviewMouseDown(object sender, MouseButtonEventArgs e) { // first did the user click on a tree node? var source = e.OriginalSource as DependencyObject; while (source != null && !(source is TreeViewItem)) { source = VisualTreeHelper.GetParent(source); } var itemSource = source as TreeViewItem; if (itemSource == null) { return; } var treeView = sender as TreeView; if (treeView == null) { return; } bool undoSelection = TreeViewSelectionChangedBehavior.GetUndoSelection(treeView); if (undoSelection == false) { return; } // Cancel the attempt to select an item. var result = MessageBox.Show("The current document has unsaved data. Do you want to continue without saving data?", "Are you really sure?", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No); if (result == MessageBoxResult.No) { // Cancel the attempt to select a differnet item. e.Handled = true; } else { // Lets disable this for a moment, otherwise, we'll get into an event "recursion" treeView.PreviewMouseDown -= uiElement_PreviewMouseDown; // Select the new item - make sure a SelectedItemChanged event is fired in any case // Even if this means that we have to deselect/select the one and the same item if (itemSource.IsSelected == true) { itemSource.IsSelected = false; } itemSource.IsSelected = true; // Lets enable this to get back to business for next selection treeView.PreviewMouseDown += uiElement_PreviewMouseDown; } }
/// <summary> /// This method is called when the selection changed event occurs. The sender should be the control /// on which this behaviour is attached - so we convert the sender into a <seealso cref="UIElement"/> /// and receive the Command through the <seealso cref="GetChangedCommand"/> getter listed above. /// /// The <paramref name="e"/> parameter contains the standard EventArgs data, /// which is unpacked and reales upon the bound command. /// /// This implementation supports binding of delegate commands and routed commands. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void Selection_Changed(object sender, RoutedPropertyChangedEventArgs <object> e) { var uiElement = sender as TreeView; // Sanity check just in case this was somehow send by something else if (uiElement == null) { return; } ICommand changedCommand = TreeViewSelectionChangedBehavior.GetChangedCommand(uiElement); // There may not be a command bound to this after all if (changedCommand == null) { return; } ////if ((e.NewValue == null && e.NewValue == null)) //// return; ////else ////{ //// // Actual value did not really change //// if ((e.NewValue != null && e.NewValue != null)) //// { //// if ((e.NewValue == e.NewValue)) //// return; //// } ////} // Check whether this attached behaviour is bound to a RoutedCommand if (changedCommand is RoutedCommand) { // Execute the routed command (changedCommand as RoutedCommand).Execute(e.NewValue, uiElement); } else { // Execute the Command as bound delegate changedCommand.Execute(e.NewValue); } }