Commands in Style

Topics: Prism v2 - Silverlight 3
Apr 23, 2010 at 11:46 AM

Hi,

I am new to PRISM archtecture and need help/views on this issue. In my application, there is a requirement of a button inside the TabHeader. The click on the button should close the TabItem (much like IE). To do this, I have two approaches:-

 

     1:- Create a region in the HeaderTemplate for TabHeader, and place the button inside the region through "RegisterViewWithRegion" method in the Initialize method of viewmodel class(derived from IModule) of corresponding module . 

       <Style x:Key="TabItemHeaderStyle" TargetType="basics:TabItem">
        <Setter Property="HeaderTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid  >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition  Width="*"/>
                            <ColumnDefinition  Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0" Text="{Binding TabHeader}" HorizontalAlignment="Center" Margin="0,0,2,0"></TextBlock>
                        <ContentControl Grid.Column="1" regions:RegionManager.RegionName="CancelRegion"  Margin="0,0,8,0"/>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

 

In the module class 
regionManager.RegisterViewWithRegion("CancelRegion", typeof(CancelButton));

  2:- Place the button inside the Style and Handle it's Click Via commanding:-

<Style x:Key="TabItemHeaderStyle" TargetType="basics:TabItem">
        <Setter Property="HeaderTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition  Width="*"/>
                            <ColumnDefinition  Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0" Text="{Binding TabHeader}" HorizontalAlignment="Center" Margin="0,0,2,0"></TextBlock>
                        <Button Content="x" Grid.Column="1" command:TabClose.Command="{Binding Path=TabCloseCommand}"  Style="{StaticResource CancelButtonStyle}" Margin="2,0,0,0"  ></Button>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
In my application, the TabItems are created through TabRegionAdapter. The Tabcontrol is placed in Shell.

Is there a better way to achieve this or Of the above two approaches, which one is better in terms of UI standards. (I know, both are violating the standards upto some extent :)   ).  Ay help is highly appreciated.


 

 

Developer
Apr 30, 2010 at 5:22 PM

Hi,

I don’t know your exact scenario, but it looks like the second approach is a simpler way to achieve that functionality. In this case the TabCloseCommand should reside in the ViewModel, which makes more sense (for example each ViewModel can provide custom logic for allowing/disallowing the closing of the tab) .

In case you added the CancelButton as a view, if several tabs are shown at the same time (which is very likely to happen), multiple instances of CancelRegion would be shown. In order for that to be possible, you should use Scoped Regions, which would add more complexity to your application.

On the other hand, you probably want all the tabs to look the same and be able to provide different behaviors when you close them. Having the ViewModel provide a Closing command and the region the defining the header style, seems to be more straight forward for this scenario.

As an additional note, I noticed you mention “in the Initialize method of viewmodel class(derived from IModule)”. It is not recommended for the ViewModel class to inherit from IModule. A module can manage ViewModels, but shouldn’t be a ViewModel itself.

I hope you find this helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi