简体   繁体   中英

Pass Element as CommandParameter from root of ElementTree

I searched a lot through Google and StackOverflow, but nothing answered my problem.

I have two Xaml Files:

MainWindow.xaml

<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>

And the MainMenu.xaml

<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>

And here my Problem occurs. Instead of passing the Mainwindow-object I want to pass the DockingManager x:Name="dockingManager" from MainWindow. But if i try to reference the object by its name it fails...

I tried the following Bindings:

CommandParameter="{Binding ElementName=dockingManager}"
CommandParameter="{Binding ElementName=dockingManager, RelativeSource={RelativeSource AncestorType=Window}}"

So how can I find and reference an Object ( dockingManager ) from the ElementTree within xaml. I want to avoid using extra code in Code-behind.

Try CommandParameter="{Binding ElementName=dockingManager, Path=.}" .

EDIT: The previous answer would not work. Here's a working idea...

In the Window.xaml:

<custom:MainMenu Grid.Row="0" Tag="{Binding ElementName=dockingManager}" />

In the MainMenu.xaml:

<UserControl x:Name="UcMainMenu" />
...
    <MenuItem Header="{t:Translate MENU_LAYOUT_SAVE}" Command="{Binding SaveLayoutCommand}" CommandParameter="{Binding ElementName=UcMainMenu, Path=Tag}"/>

您可以使用:

CommandParameter="{x:Reference Name=yourElementName}"

Since you are using MVVM here is what you should do to come up with a slightly different solution:

  • Get rid of the CommandParameter
  • The command will trigger a callback in the MainWindowViewModel instance
  • This callback will change some state/properties in the MainWindowViewModel instance
  • The DockingManager instance reacts to that adjusted state of the MainWindowViewModel instance through bindings

The way you are doing it now is way too complicated. In addition to that, you are wildly mixing patterns here. MVVM tries to separate the business logic from the actual elements. You are using elements of MVVM with Smart UI/Code Behind techniques.

Also, consider using individual view models for individual controls. The main menu control is separate and the docking manager is, too. Why? Because you want to break everything into smaller pieces, but more importantly, because you might have reusability in mind. With the main menu trying to access a docking manager inside a Window that is not possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM