C# 从ElementTree的根以CommandParameter的形式传递元素
我在谷歌和StackOverflow上搜索了很多,但都没有找到答案 我有两个Xaml文件: main window.xamlC# 从ElementTree的根以CommandParameter的形式传递元素,c#,wpf,xaml,data-binding,mvvm,C#,Wpf,Xaml,Data Binding,Mvvm,我在谷歌和StackOverflow上搜索了很多,但都没有找到答案 我有两个Xaml文件: main window.xaml <Window x:Name="mainWindow"> <Window.DataContext> <!-- Instantiate ViewModel of the MainWindow --> <vm:MainWindowViewModel x:Name="viewModel"/>
<Window x:Name="mainWindow">
<Window.DataContext>
<!-- Instantiate ViewModel of the MainWindow -->
<vm:MainWindowViewModel x:Name="viewModel"/>
</Window.DataContext>
<!-- Create the Menu of the MainWindow -->
<custom:MainMenu Grid.Row="0"/>
<ad:DockingManager x:Name="dockingManager">
<!-- ... -->
</Window>
<UserControl>
<Menu>
<MenuItem Header="{t:Translate MENU_LAYOUT_SAVE}" Command="{Binding SaveLayoutCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
<MenuItem Header="{t:Translate MENU_LAYOUT_LOAD}" Command="{Binding LoadLayoutCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
</Menu>
</UserControl>
因此,如何从xaml中的ElementTree中查找和引用对象(
dockingManager
)。我想避免在代码隐藏中使用额外的代码。尝试CommandParameter=“{Binding ElementName=dockingManager,Path=。}”
编辑:
前面的答案行不通。这里有一个可行的想法
在Window.xaml中:
<custom:MainMenu Grid.Row="0" Tag="{Binding ElementName=dockingManager}" />
在main menu.xaml中:
<UserControl x:Name="UcMainMenu" />
...
<MenuItem Header="{t:Translate MENU_LAYOUT_SAVE}" Command="{Binding SaveLayoutCommand}" CommandParameter="{Binding ElementName=UcMainMenu, Path=Tag}"/>
...
试试CommandParameter=“{Binding ElementName=dockingManager,Path=.}”
编辑:
前面的答案行不通。这里有一个可行的想法
在Window.xaml中:
<custom:MainMenu Grid.Row="0" Tag="{Binding ElementName=dockingManager}" />
在main menu.xaml中:
<UserControl x:Name="UcMainMenu" />
...
<MenuItem Header="{t:Translate MENU_LAYOUT_SAVE}" Command="{Binding SaveLayoutCommand}" CommandParameter="{Binding ElementName=UcMainMenu, Path=Tag}"/>
...
既然您使用的是MVVM,那么您应该做些什么来提出一个稍微不同的解决方案:
- 去掉
CommandParameter
- 该命令将在
实例中触发回调MainWindowViewModel
- 此回调将更改
实例中的某些状态/属性MainWindowViewModel
实例通过绑定对DockingManager
实例的调整状态作出反应MainWindowViewModel
也可以考虑使用单独的视图模型来进行单独的控件。主菜单控件是独立的,停靠管理器也是独立的。为什么?因为你想把所有的东西分解成更小的部分,但更重要的是,你可能会考虑到可重用性。当主菜单试图访问
窗口中的停靠管理器时,这是不可能的。由于您使用的是MVVM,因此您应该采取以下措施来提出稍微不同的解决方案:
- 去掉
CommandParameter
- 该命令将在
MainWindowViewModel
实例中触发回调
- 此回调将更改
MainWindowViewModel
实例中的某些状态/属性
DockingManager
实例通过绑定对MainWindowViewModel
实例的调整状态作出反应
你现在做这件事的方式太复杂了。除此之外,你们还在这里疯狂地混合模式。MVVM试图将业务逻辑与实际元素分开。您正在使用具有智能UI/代码隐藏技术的MVVM元素
也可以考虑使用单独的视图模型来进行单独的控件。主菜单控件是独立的,停靠管理器也是独立的。为什么?因为你想把所有的东西分解成更小的部分,但更重要的是,你可能会考虑到可重用性。主菜单试图访问
窗口中的停靠管理器,这是不可能的。您可以使用:
CommandParameter="{x:Reference Name=yourElementName}"
您可以使用:
CommandParameter="{x:Reference Name=yourElementName}"
这会更优雅,但问题很简单,这并不能回答问题。@CodeMonkey你完全正确。我忍不住给出建议而不是回答(事实上我现在没有)。这是可以理解的,我会敦促用户823、5353考虑使用这个建议:你能再详细地说明一下你的建议吗?我通过绑定传递dockingManager
的方法有什么不好?@user2823573我调整了我的答案。这会更优雅,但问题很简单,这并不能回答问题。@CodeMonkey你完全正确。我忍不住给出建议而不是回答(事实上我现在没有)。这是可以理解的,我会敦促用户823、5353考虑使用这个建议:你能再详细地说明一下你的建议吗?我通过绑定传递dockingManager
的方法有什么不好?@user2823573我调整了我的答案。感谢快速重播。我也试过了。失败,返回System.Windows.Data错误:4:找不到引用为“ElementName=dockingManager”的绑定源。BindingExpression:Path=。;DataItem=null;目标元素是“MenuItem”(名称=“”);目标属性为“CommandParameter”(类型为“Object”)
谢谢。这对我来说很有效,但看起来有点像肮脏的解决办法。可能我会保留一段时间,然后按照meilke描述的方式进行。这是一种变通方法,原因很简单:如果您有一个直接依赖于自身之外的控件的UserControl,那么可能这不是真正的UserControl。你试图做的事情并不是很好的实践,所以我强烈建议你试试梅尔克所描述的或类似的东西。一般来说,尽量避免UI中的横向依赖性(可能除了涉及简单外观和样式的任何情况),并坚持使用VM数据。只是对我发布的解决方案的一点评论:要做到这一点,一个稍微好一点的方法(不是黑客式的)是使用专用的DependencyProperty(例如,“DockingManagerDependencyProperty”)实际上,我只是考虑了我刚才说过的话:在我看来,这是一个很好的实践。为什么?MVVM的一个陷阱是试图把所有东西都推到VM中。总是这样想:你能想象一个没有特征A的应用程序的UI吗?(例如,没有停靠的静态UI)?如果是这样,那么功能A就不应该合并到VM中,因为VM应该是UI不可知的。感谢快速重播。也尝试过。失败原因是System.Windows。数据错误:4:找不到引用“ElementName=dockingManager”的绑定源。BindingExpression:Path=;DataItem=null;目标元素是“MenuItem”(Name=“”);目标属性为“CommandParameter”(类型)