2
votes

I have two buttons in one View, is it possible to bind one button to one command in first ViewModel and another button bind to second command in second ViewModel? Just to add both ViewModels are initialized.

    <Button Command="{Binding ElementName=MainTreeView, Path=DataContext.FirstCommand}" CommandParameter="{Binding NameE}">
    <Label Content="{Binding NameE}"/>
 </Button>
  <Button Command="{Binding ElementName=MainTreeView, Path=DataContext.SecondCommand}" CommandParameter="{Binding NameD}">
    <Label Content="{Binding NameD}"/>
 </Button>

And my two ViewModels:

public class FirstViewModel : INotifyPropertyChanged
{
     public MyICommand<string> FirstCommand { get; private set; }

     public HomeViewModel()
    {
        FirstCommand = new MyICommand<string>(myFirstCommand);
    }

    public void myFirstCommand(string par)
    {
        Console.Beep();
    }
}


public class SecondViewModel : INotifyPropertyChanged
{
     public MyICommand<string> SecondCommand { get; private set; }

     public HomeViewModel()
    {
        SecondCommand = new MyICommand<string>(mySecondCommand);
    }

    public void mySecondCommand(string par)
    {
        Console.Beep();
    }
}

EDIT: In a view where are buttons i have <ContentPresenter Content="{Binding Content}"/> and that Content have View with a ViewModel i wanna reach with buttons

1
depends on how view and view models are wired together - ASh
In a view where are buttons i have <ContentPresenter Content="{Binding Content}"/> and that Content have View with a ViewModel i wanna reach with buttons. - Filip Filipovic
Have you considered making the two ViewModels properties of a parent ViewModel and then linking to them through this? - Gregor A. Lamche
I didn't, i will look into it. Thanks. - Filip Filipovic

1 Answers

2
votes

The easiest and most generic solution is to make your view models globally accessible by instantiating them in the App.xaml ResourceDictionary:

App.xaml:

<Application ...>
  <Application.Resources>
    <ResourceDictionary>
      <FirstViewModel x:Key="FirstViewModel" />
      <SecondViewModel x:Key="SecondViewModel" />
    </ResourceDictionary>
  </Application.Resources>
</Application>

or using C# (e.g., App.xaml.cs)

Application.Current.Resources.Add("FirstViewModel", new FirstViewModel(arg1, arg2));
Application.Current.Resources.Add("SecondViewModel", new SecondViewModel(arg1, arg2));

Now you can reference them from any view:

<Button Content="{Binding NameE}" 
        CommandParameter="{Binding NameE}" 
        Command="{Binding Source={StaticResource FirstViewModel}, Path=FirstCommand}" />

<Button Content="{Binding NameD}" 
        CommandParameter="{Binding NameD}" 
        Command="{Binding Source={StaticResource SecondViewModel}, Path=SecondCommand}" />

Another solution is to use composition and wrap the view models into a parent view model:

public class MainViewModel : INotifyPropertyChanged
{
  public FirstViewModel FirstViewModel { get; private set; }
  public SecondViewModel SecondViewModel { get; private set; }

  public MainViewModel()
  {
    this.FirstViewModel = new FirstViewModel();
    this.SecondViewModel = new SecondViewModel();
  }
}

public class FirstViewModel : INotifyPropertyChanged
{
  public MyICommand<string> FirstCommand { get; private set; }

  public FirstViewModel()
  {
    FirstCommand = new MyICommand<string>(myFirstCommand);
  }

  public void myFirstCommand(string par)
  {
    Console.Beep();
  }
}


public class SecondViewModel : INotifyPropertyChanged
{
  public MyICommand<string> SecondCommand { get; private set; }

  public SecondViewModel()
  {
    SecondCommand = new MyICommand<string>(mySecondCommand);
  }

  public void mySecondCommand(string par)
  {
    Console.Beep();
  }
}

Usage

<TreeView x:Name="MainTreeView">
  <TreeView.DataContext>
    <MainViewModel />
  </TreeView.DataContext>
</TreeView>


<Button Content="{Binding NameE}" 
        CommandParameter="{Binding NameE}" 
        Command="{Binding ElementName=MainTreeView, Path=DataContext.FirstViewModel.FirstCommand}" />

<Button Content="{Binding NameD}" 
        CommandParameter="{Binding NameD}" 
        Command="{Binding ElementName=MainTreeView, Path=DataContext.SecondViewModel.SecondCommand}" />