我有一个2级WPF树视图。当我单击子项时,会触发正确的selectedCommand并且一切正常。
但是当我点击我的详细信息视图并更新此选定项目的字段时,它会取消选择我的childItem并触发父命令,因为父项已被选中,但我需要保持我的childItem被选中。
我找到了一些关于同一问题的主题,但我使用命令进行绑定,而不仅仅是代码隐藏,所以我不知道如何让这个解决方案适合我。
触发我的命令:
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction
Command="{Binding ItemSelectedCommand}"
CommandParameter="{Binding SelectedItem, ElementName=TreeView}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
我的树视图:
<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>
这是我的命令,它在我的ViewModel文件中
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
}
}
因此,当我在树视图中选择一个项目时触发相同的命令,但是当我选择子项时,父事件也会被触发,因此我的命令被触发2次并激活我的父视图并且不会停留在我的孩子看来。如果我已通过子命令,如何停止传播事件?如何使用我的命令而不是后面的代码?
编辑
这是我的函数ActivateDetailsView(),由我的SelectedCommand调用 我有13个模块,每个模块都有一个detailsView,所以当我点击我选择的项目时,我将使用反射性搜索我需要激活的视图,并使用PRISM库来激活它。
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);
}
}
重现问题:启动一个新的WPF项目,在解决方案中添加一个主项目,其中包含一个带树视图的视图和一个treeviewviewmodel,其中包含将在您的树视图中显示的ParentViewModel列表。使用2个视图模型定义另一个项目:一个具有ObservableCollection的类ParentVM和一个childViewModel,让一个或两个属性像name一样,并将其绑定到treeview。在第二个项目中,定义detailsView以查看ChildViewModel的属性。在您的主项目中,在treeviewviewmodel中添加一个SelectedCommandFunction,它使用prism来激活您的detailView。 (单击Parent时需要有一个DetailsView,单击ChildView时需要另一个。
答案 0 :(得分:0)
每个TreeViewItem
都在其父级的可视树中,并且事件将向下冒泡,因此如果您单击树叶,并且它有两个父级,则该事件将被调用3次。
防止这种情况的方法:
IsSelected
的{{1}}直接绑定到您的VM的TreeItem
,并执行您的VM的IsSelected
属性OnPropertyChanged
。IsSelected
是否与发件人相同(类似于here)