0

I'm using prism TabControl Region inside the shell view.

Each TabItem contains AView and AViewModel.

I can determine the currently active TabItem using a property IsActive property in AViewModel.

IsActive property is set to true only for the current selected TabItem.

I have button inside the Shell view, which is responsible for executing logic for the views inside the TabItems.

What's the right way to enable disable the button according the current active TabItem(set can execute command to true or false), and execute the logic only for the active view. from a button placed in other view?

I have managed to execute the command by creating composite command, and then register the commands from the AViewModel to the composite command, and bind the button inside the shell to the composite command.

The problem with this approach, that if any of the commands return false which they're all except one (the active TabItem), none of the commands executed.

The CompositeCommand class maintains a list of child commands (DelegateCommand instances). The Execute method of the CompositeCommand class simply calls the Execute method on each of the child commands in turn. The CanExecute method similarly calls the CanExecute method of each child command, but if any of the child commands cannot be executed, the CanExecute method will return false. In other words, by default, a CompositeCommand can only be executed when all the child commands can be executed. Source

IBRA
  • 1,502
  • 3
  • 24
  • 56
  • That's the thing, in large applications which for example use regions like in Prism, you save the active region always. Exactly for that reason, for when you have to execute a command and handle it within a certain context. So it's not enough to have the active region in your ViewModel, you got to have it exposed and available system wide. – Mishka Jun 21 '17 at 17:31

3 Answers3

1

If you are using a CompositeCommand, and only want to invoke the command on the active Tab, then have your ViewModels implement IActiveAware. Then in the ctor of your CompositeCommand, pass true as the parameter. This will then monitor only the active tab.

  • I'm using this, but the commands doesn't seems to work, the buttons are always disabled even i'm returning true all the time. – IBRA Jun 29 '17 at 07:30
  • I've fixed it by setting the command IsActive property to the current active value. `MyCommand.IsActive = IsActive` , but I need to do this for every command, is there a better way? or this is an acceptable solution? – IBRA Jun 29 '17 at 10:27
  • That how you are supposed to do it. In the IsActive property setter, set the Command.IsActive property to the value. –  Jun 29 '17 at 13:58
0

Create a service known to both the view models of the tabs and the shell's view model. When a tab view model gets active, it announces itself to the service. The shell view model either looks at the service for the command (who in turn forwards to the active tab view model), or (prefered), the service hosts the command and just uses the information provided by the tab view model.

Haukinger
  • 10,420
  • 2
  • 15
  • 28
0

CompositeCommand is obviously the wrong command to use as it's designed to execute on multiple targets and you only ever want it to execute on a single target, the active viewmodel.

Without seeing either code or XAML, it's difficult to give advice but assuming that the XAML looks something like this:

<Grid>
 <Grid.RowDefinitions>
  <RowDefiniton Height="Auto" />
  <RowDefinition />
 </Grid.RowDefinitions>

 <Button Grid.Row="0" Content="Execute on Active" />
 <TabControl Grid.Row="1" ItemSource="{Binding TabViewModels}" prism:RegionManager.RegionName="TabRegion" IsSynchronizedWithCurrentItem="True" />

<Grid>

then the simplest way to execute a command on the active item is to set the Command property on the Button to the active viewmodel's TargetCommand using the "/" syntax, which denotes the current item.

<Button Grid.Row="0" Content="Execute on Active" Command="{Binding TabViewModels/TargetCommand}" />
Amen Jlili
  • 1,884
  • 4
  • 28
  • 51
Barracoder
  • 3,696
  • 2
  • 28
  • 31
  • 1
    Not true. It works for single active regions too, and ignores all others. –  Jun 26 '17 at 23:36