10

I would like to change the content of the main surface (the stuff below the ribbon itself)in a WPF application when a ribbon tab is clicked. I'm using the office ribbon, not that is matters much. So which WPF container control should I use, and how would I do it? Should I just have various controls with visibility hidden, or what. I'm not a WPF expert so I need a little inspiration.

GEOCHET
  • 21,119
  • 15
  • 74
  • 98
Klaus Byskov Pedersen
  • 117,245
  • 29
  • 183
  • 222
  • 1
    I think according to Microsoft's ULA, you can not use ribbon UI which can change content of main surface area when you change tab. Each tab is only supposed to have buttons of toolbar and not change the appearance of content. – Akash Kava Dec 04 '09 at 15:23
  • I'm not sure that you are right. Think about how Word works, when you change view mode. – Klaus Byskov Pedersen Dec 04 '09 at 15:49
  • Klaus, can you please provide more details on how you solved this? – l33t May 10 '12 at 15:07

4 Answers4

11

Ill preface by saying I doubt this is the best way to do this.

This is my style for RibbonTab notice IsSelected is bound to IsSelected in The view model

  <!-- RibbonTab -->
        <Style TargetType="{x:Type ribbon:RibbonTab}">
            <Setter Property="ContextualTabGroupHeader" Value="{Binding ContextualTabGroupHeader}" />
            <Setter Property="Header" Value="{Binding Header}" />
            <Setter Property="ItemsSource" Value="{Binding GroupDataCollection}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected}" />
        </Style>

This is view model code

    public bool IsSelected
    {
        get
        {
            return _isSelected;
        }

        set
        {
            if (_isSelected != value)
            {
                _isSelected = value;
                OnPropertyChanged(new PropertyChangedEventArgs("IsSelected"));
            }
        }
    }
    private bool _isSelected;

In the constructor for the TabViewModel I take a parameter for the ViewModel of the content

    public TabData(ISelectedContentTab content)
        : this(content.DisplayName)
    {
        _selectedContent = content;
    }

    private ISelectedContentTab _selectedContent;

Then I used an ItemsControl to display the selected content in my xaml

  <ItemsControl Grid.Row="1" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch" 
                  ItemsSource="{Binding ElementName=ribbon,Path=SelectedItems}" 
                  ItemTemplate="{StaticResource ContentControlTemplate}" />

And the ContentControlTemplate I have is

 <DataTemplate x:Key="ContentControlTemplate">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <ContentControl Grid.Row="0" VerticalAlignment="Stretch" Height="Auto" VerticalContentAlignment="Stretch" Content="{Binding SelectedContent}" />
            </Grid>
        </DataTemplate>

Also make sure you have a datatemplate pointing your content to a view

Hope this helps.

Wegged
  • 2,383
  • 20
  • 26
  • 1
    Please provide more details! These code fragments are not enough to make my day :) – l33t May 10 '12 at 14:55
9

The idea is to have content below ribbon stacked in layers, (like in Photoshop or any other graphical editor) and show only layer you need this moment. Just bind Visibility of your layer to IsSelected property of desired tab

MainGrid here is a container for layers (which are Grids too):

    <Grid x:Name="MainGrid">
        <Grid Visibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, ElementName=ribbonTab2}">
            <Image x:Name="ImgMain" Source="x.jpg"/>
        </Grid>
        <Grid Visibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}, ElementName=ribbonTab1}">
            <Image x:Name="ImgXtra" Source="y.jpg"/>
       </Grid>
    </Grid>

Add <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> in resources.

...and you don't need any code at all!

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Wolfrevok Cats
  • 167
  • 1
  • 7
2

I guess there is a more simpler way to do it. I have done it like this:

<Frame NavigationUIVisibility="Hidden" x:Name="FrmMainFrame" DockPanel.Dock="Bottom"/>

And in your code behind:

mainWindowView.RibMain.SelectionChanged += RibMain_SelectionChanged;

void RibMain_SelectionChanged(object sender,  System.Windows.Controls.SelectionChangedEventArgs e)
    {
        var tab = this.mainWindowView.RibMain.SelectedItem as RibbonTab;
        if (tab.Header.Equals("Explorer"))
        {
            mainWindowView.FrmMainFrame.Navigate(explorerController.View());
        }
        else
            mainWindowView.FrmMainFrame.NavigationService.Navigate(new Uri("http://www.google.com/"));
    }
Nawed Nabi Zada
  • 2,819
  • 5
  • 29
  • 40
1

I've discovered a solution:

Give your RibbonTab a name so you can handle it in the code behind. I know there are multiple ways to add views and controls, but here is what I did... I simply added a new grid for my view within the main Grid after the Ribbon. ie:

<r:RibbonWindow>
  <Grid>
    <r:Ribbon>
      <r:RibbonTab Name="Tab1" Header="Home">
        <r:RibbonGroup Name="Group1">
          <r:RibbonButton LargeImageSource="images\icon.png" Label="Click Me"/>
        </r:RibbonGroup>
      </r:RibbonTab>
      <r:RibbonTab Name="Tab2" Header="Other Tab">
        <r:RibbonGroup Name="Group2">
          <r:RibbonButton LargeImageSource="images\icon.png" Label="Click Me"/>
        </r:RibbonGroup>
      </r:RibbonTab>
    </r:Ribbon>
    <Grid Name="Tab1RTB" Grid.Row="1" Visibility="Hidden">
      <RichTextBox Margin="5" BorderBrush="LightGray" BorderThickness="1"/>
    </Grid>
    <Grid Name="Tab2RTB" Grid.Row="1" Visibility="Hidden">
      <RichTextBox Margin="5" BorderBrush="LightGray" BorderThickness="1"/>
    </Grid>
  </Grid>
</r:RibbonWindow>

Then the code behind (VB.NET)

Private Sub TabChanged(sender As System.Object, e As SelectionChangedEventArgs) Handles ribbonHome.SelectionChanged
  If Tab1.IsSelected = True Then
    Tab1RTB.Visibility = Windows.Visibility.Visible
    Tab2RTB.Visibility = Windows.Visibility.Collapsed
  ElseIf Tab2.IsSelected = True
    Tab1RTB.Visibility = Windows.Visibility.Collapsed
    Tab2RTB.Visibility = Windows.Visibility.Visible
  Else
    Tab1RTB.Visibility = Windows.Visibility.Collapsed
    Tab2RTB.Visibility = Windows.Visibility.Collapsed
  End If
End Sub
StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Dethlore
  • 11
  • 3