I have a 2 level WPF treeview. When I click on a child item, the correct selectedCommand is triggered and all works well.
But when I click on my details view and update the field of this selected item, it unselect my childItem and fired the parent command because the parent is selected, but I need to just keep my childItem selected.
I have found some topics about the same problem, but I use command for my binding and not just code behind so I don't know how to make this solution work for me.
- Dispacher.BeginInvoke method : > Parent TreeView Item ghost selected event!
- e.Handled : > WPF TreeviewItem parent selected event fired after selecting a child?
- And a topic that said it's a focus problem : TreeView auto-selecting parent after user selects child
Trigger of my command :
<i:Interaction.Triggers> <i:EventTrigger EventName="SelectedItemChanged"> <i:InvokeCommandAction Command="{Binding ItemSelectedCommand}" CommandParameter="{Binding SelectedItem, ElementName=TreeView}"/> </i:EventTrigger> </i:Interaction.Triggers> My Treeview :
<TreeView x:Name="TreeView" ItemsSource="{Binding Modules}"> <HierarchicalDataTemplate DataType="{x:Type module:ParentViewModel}" ItemsSource="{Binding ChildItems}"> <TextBlock Text="Parent"/> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="{x:Type module:ChildViewModel}"> <TextBlock Text="{Binding Path=childName}"/> </HierarchicalDataTemplate> </TreeView> And here is my command which is in my ViewModel file
public ICommand ItemSelectedCommand { get { return _itemSelectedCommand ?? (_itemSelectedCommand = new CommandHandler(param => SelectedCommand(param))); } } public void SelectedCommand(object selectedItem) { //code to activate my details view with prism if(selectedItem.GetType().Name == "ParentType") { ActivateParentView(); } else { ActivateDetailsView(.....); //activate child view } } So, I trigger the same command when selected an item in my treeview but when I select the child item, the parent event is also triggered so my command is triggered 2 times and activate my parent view and don't stay in my child view. How can I stop propagating the event if I have already pass through child command ? How can I make it working with my command and not in code behind ?
EDIT
Here is my function ActivateDetailsView() which is called by my SelectedCommand I have 13 modules and I have one detailsView in each module, so when I click on my selected item, I will search using reflexivity for the view I need to activate and I use PRISM library to activate it.
private void ActivateDetailsView(string nameTypeItem,IRegion tabConfigurationRegion, ModuleItemBaseViewModel selectedItem) { try { string viewName = "ModuleItem" + nameTypeItem + "DetailsView"; string moduleName = "Module" + nameTypeItem; string fullViewName = moduleName + ".Views." + viewName + ", " + moduleName; var typeOfCurrentView = Type.GetType(fullViewName); //var view = Activator.CreateInstance(typeOfCurrentView); var view = tabConfigurationRegion.GetView(viewName); if (view == null) { view = _container.Resolve(typeOfCurrentView); // Add the view to the main region. This automatically activates the view too. tabConfigurationRegion.Add(view, viewName); } // The view has already been added to the region so just activate it. tabConfigurationRegion.Activate(view); string viewModelName = "ModuleItem" + nameTypeItem + "DetailsViewModel"; string fullViewModelName = moduleName + ".ViewModels." + viewModelName + ", " + moduleName; var typeOfCurrentViewModel = Type.GetType(fullViewModelName); //equivalent to ModuleItemSiemensDetailsViewModel viewModelM = view.DataContext as ModuleItemSiemensDetailsViewModel; var propertyInfoDataContext = view.GetType().GetProperty("DataContext"); var viewModelModuleItem = propertyInfoDataContext.GetValue(view, null); if (viewModelModuleItem != null) { PropertyInfo prop = typeOfCurrentViewModel.GetProperty("CurrentModuleItem"); //equivalent to viewModelModuleItem.CurrentModuleItem = selectedItem as ModuleItemBaseViewModel; prop.SetValue(viewModelModuleItem, selectedItem, null); } } catch (Exception ex) { Debug.WriteLine(ex.Message); Debug.WriteLine(ex.StackTrace); } } To reproduce the problem : Start a new WPF project, Add one main project in your solution with a view with a treeview and a treeviewviewmodel with the list of ParentViewModel which will be display on your treeview. Define an other project with 2 viewmodels : one class ParentVM with an ObservableCollection and a childViewModel, let one or two property like name, and bind it to the treeview. In the second project, define a detailsView to see properties of your ChildViewModel. On your main project, in the treeviewviewmodel add a SelectedCommandFunction which use prism to activate your detailView. (You need to have a DetailsView when you click on the Parent and an other one when you click on the ChildView.
Application.Current.Dispatcher.Invoketo reset it) during update.<StackPanel> <TextBlock Text="Name:" /> <TextBox Text="{Binding Path=CurrentModuleItem.Name}" /> </StackPanel>. I will just add my real function which activate the view because it use PRISM for it and maybe it's the way I am using prism which is incorrect ...