Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Command with multiple target types

Tags:

command

wpf

I'm a bit confused about WPF commands with different target types.

So if I define a command

<Window.CommandBindings>
        <CommandBinding Command="Copy"
                        Executed="CopyCmdExecuted"
                        CanExecute="CopyCmdCanExecute"/>

    </Window.CommandBindings>

And now I use it in a context menu:

                    <ContextMenu Name="FolderContextMenu">
                        <MenuItem Command="Copy"/>
                        </ContextMenu>

And I have a method to handle the command:

private void CopyCmdExecuted(object sender, ExecutedRoutedEventArgs e)
{


}

And I use it in a plain old menu:

    <Menu  Name="editMenu">
        <MenuItem Command="Copy"/>
    </Menu>

I have no problem understanding that. But I'm a bit confused what I am supposed to do if the target objects are different types.

Lets say I have Folders and Users, both of which have a context menu with the New command (and the menu bar edit menu which also has the New command).

When New is executed, regardless of whether its a Folder or a User, CopyCmdExecuted is executed. So, am I now supposed to de-multiplex on the target? Something like

   private void CopyCmdExecuted(object sender, ExecutedRoutedEventArgs e)
        {
           if(sender is User)
               // Do copy user stuff
           if(sender is Folder)
               // Do copy folder stuff
        }

If I end up with lots of data types I wish to copy, it seems a bit annoying. Am I not understanding something here?

(Obviously, I could just have Folder and User inherit from a Copiable base class with DoCopy but that still seems wrong.)

like image 619
user570577 Avatar asked Jan 11 '11 00:01

user570577


1 Answers

You can send a CommandParameter when you invoke the Command to indicate what you mean the command to apply to. Here's are two TextBlock elements:

<Grid>
    <StackPanel>
        <TextBlock Name="textBlock1" Text="File">
            <TextBlock.ContextMenu>
                <ContextMenu>
                    <MenuItem
                        Command="Copy"
                        CommandParameter="{Binding PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
                </ContextMenu>
            </TextBlock.ContextMenu>
        </TextBlock>
        <TextBlock Name="textBlock2" Text="Folder">
            <TextBlock.ContextMenu>
                <ContextMenu>
                    <MenuItem
                        Command="Copy"
                        CommandParameter="{Binding PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
                </ContextMenu>
            </TextBlock.ContextMenu>
        </TextBlock>
    </StackPanel>
</Grid>

and this code-behind:

    private void CopyCmdExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        var text = (e.Parameter as TextBlock).Text;
        Debug.WriteLine("Text = " + text);
    }

uses the parameter to figure out which TextBlock the context menu applies to. You can also just use the strings "File" and "Folder" if that works for you.

like image 178
Rick Sladkey Avatar answered Oct 12 '22 21:10

Rick Sladkey