0
votes

I have a mainwindow inside which there is a usercontrol which contains a listview. User control also has a button which copies all the contents of listview to clipboard. This is how the copy functionality has been implemented. below is a part of xaml of usercontrol -

<Button Command="Copy" 
     CommandTarget="{Binding ElementName=testCodeView}"
     CommandParameter="Copy"
</Button> 

<ListView  x:Name="testCodeView" 
       ItemsSource="{Binding Products}" BorderThickness="0" Grid.Row="1"
       ItemTemplate="{StaticResource testViewTemplate}"       
       ItemContainerStyle="{StaticResource testCodesListItem}"
       infra:AttachedProperties.CommandBindings ="{Binding CommandBindings}">
</ListView>

The AttachedProperties class holds the Dependency property "CommandBindings" - below is the code -

public class AttachedProperties
{
public static DependencyProperty CommandBindingsProperty =
        DependencyProperty.RegisterAttached("CommandBindings", typeof(CommandBindingCollection), typeof(AttachedProperties),
        new PropertyMetadata(null, OnCommandBindingsChanged));
public static void SetCommandBindings(UIElement element, CommandBindingCollection value)
    {
        if (element != null)
            element.SetValue(CommandBindingsProperty, value);
    }
    public static CommandBindingCollection GetCommandBindings(UIElement element)
    {
        return (element != null ? (CommandBindingCollection)element.GetValue         (CommandBindingsProperty) : null);
    }
}

Below is the usercontrol viewmodel's code related to copying the items of listview.

public class UserControlViewModel : INotifyPropertyChanged
{
    public CommandBindingCollection CommandBindings
    {
        get
        {
            if (commandBindings_ == null)
            {
                commandBindings_ = new CommandBindingCollection();
            }
            return commandBindings_;
        }
    }
    public UserControlViewModel 
    {
        CommandBinding copyBinding = new CommandBinding(ApplicationCommands.Copy,   
        this.CtrlCCopyCmdExecuted, this.CtrlCCopyCmdCanExecute);
        // Register binding to class
        CommandManager.RegisterClassCommandBinding(typeof(UserControlViewModel), copyBinding);
        this.CommandBindings.Add(copyBinding);
    }
    private void CtrlCCopyCmdExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        copyToclipboard_.CtrlCCopyCmdExecuted(sender, e);
    }
}

The sender object in CtrlCCopyCmdExecuted function is the listview in usercontrol which is futher used in copying its contents. The copy all functionality works fine with the button on user control. I have to create a key binding for copy functionality in mainwindow. I have created other keybindings in mainwindow which works fine as the commands are defined in MainWindowViewModel, but since the commandbindings of the copy all command are in the usercontrol's view model, I am facing problems in linking command of keybinding in mainwindowviewmodel with the commandbinding in usercontrolviewmodel. Can Someone help me out with this.

Thanks in advance.

1

1 Answers

0
votes

If your parent view model has access to the child view model then you have two main options. Both options involve creating an ICommand property to Bind to in the parent view model:

<KeyBinding Gesture="CTRL+C" Command="{Binding Copy, Mode=OneWay}" />

The first option involves creating a BaseViewModel class that has an abstract ICommand property in it... any class that extends the BaseViewModel class has to implement this command... then you could have the child view model property of this type and simply pass the value along:

public override ICommand Copy
{
    get { return new ActionCommand(action => ViewModel.Copy.Execute(null), 
canExecute => ViewModel.Copy != null); }
}

I doubt that you want that command on every view model though, so let's investigate option two. The basic idea is that if you have access to the child view model, you can 'pass' the command along to the child:

public ICommand Copy
{
    get { return new ActionCommand(action => childViewModel.Copy.Execute(action), 
canExecute => childViewModel.Copy.Execute(canExecute)); }
}

ActionCommand is a custom class that is based on the common RelayCommand.


UPDATE >>>

Ok, so I've never used CommandBindings before because it's so much easier using my ActionCommand, or RelayCommand, but I've just investigated it on MSDN and two ideas spring to mind.

First, if you're using the ApplicationCommands.Copy command object in the child UserControl, then surely you can just use that same object in the KeyBinding in the parent view. ApplicationCommands is a static class and Copy is a static property, so wherever you call it, it's the same object:

<KeyBinding Gesture="CTRL+C" Command="ApplicationCommands.Copy" />

Failing that, you could create an ICommand property in your parent view model and either create your own Copy command, or just return the ApplicationCommands.Copy command. Then you could Bind to it from the parent view and the child view... or, you could even add it into the child view CommandBinding object from the parent view model.