0
votes

I have set up a complete application using C# .NET 4, Prism and Unity that implements the INavigationAware interface on the ViewModel of an MVVM pattern. My window (Shell.xaml) is very simple at the moment (static string for RegionName to avoid magic strings):

Shell.xaml

<Grid>
  <ContentControl prism:RegionManager.RegionName="{x:Static Infrastructure:RegionNames.ContentRegion}" />
</Grid>

Each of my views contains buttons that allow the user to open another view using a centralized CompositeCommand to which I attach a DelegateCommand in the Shell like so:

ViewA.xaml

<Button Name="AcceptButton" Content="Accept"
            Command="{x:Static Infrastructure:ApplicationCommands.NavigateCommand}"
            CommandParameter="{x:Type Concrete:ViewB}"

ApplicationCommands.cs

public static class ApplicationCommands {
    public static CompositeCommand NavigateCommand = new CompositeCommand();
}

ShellViewModel.cs

public ShellViewModel(IRegionManager regionManager) {
        _regionManager = regionManager;
        NavigateCommand = new DelegateCommand<object>(Navigate, CanNavigate);
        ApplicationCommands.NavigateCommand.RegisterCommand(NavigateCommand);
    }

private void Navigate(object navigatePath) {
        if (navigatePath != null) {
            _regionManager.RequestNavigate(RegionNames.ContentRegion, navigatePath.ToString(), NavigationCallback);
        }                  
    }

I have several more views tied in and the navigation is working great. Now comes the changes that are failing. Having random buttons on each screen is really ineffective and contrary to good design so I am trying to pull the buttons out for a centralized toolbar. I have pulled the ViewA.xaml button code out of the ViewA.xaml file ( which contains much more content but not shown for overkill reasons ) and put it into a ViewAButonn.xaml file. I then modified the Shell.xaml and add a second region:

Modified Shell.xaml

<Grid>
  <ContentControl prism:RegionManager.RegionName="{x:Static Infrastructure:RegionNames.ContentRegion}" />
  <ContentControl prism:RegionManager.RegionName="{x:Static Infrastructure:RegionNames.NavRegion}" />
</Grid>

I can add my new ViewAButton.xaml to the region without any issue and when I click it the View contents are then placed properly into the ContentRegion.

My issue arises here though. My first screen is a TOS agreement screen that cannot display the toolbar until "Accept" button is clicked. I am terrified at the thought of handling this in the ViewModel as I have it properly decoupled right now. Do I modify the View to contain a property that can be read during navigation to hide the region? If so where in the navigation process can I get access to the View that is activated by Unity? All of my views implement an IView interface that just exposes an IVewModel as per the MSDN instruction on setting up a proper prism MVVM. How can I hide this new toolbar on the TOS acceptance screen?

2

2 Answers

0
votes

Based on my understanding it would not be possible to collapse a Region. The View would get Hidden but the space where the Region is located would remain empty.

If you want the TOS screen to fill the entire window, you could create two levels of Regions:

For example, you could declare a "WindowRegion" Region in the Shell View which fills the complete Window and where the TOS screen and a defined "CustomRegionsView" would get registered.

Then, the CustomRegionsView would define both Regions you mentioned above so the App can navigate between the TOS screen and any View with the two regions you described.

Therefore, when "Accept" button is clicked from the TOS screen, Navigation to the CustomRegionsView should be performed as also to the particular Views which are registered on the ContentRegion and NavRegion.

I hope you find this helpful.

0
votes

It’s worth having a closer look at the “Prism for WPF Reference Implementation”, in particular, Shell.xaml in Line 173 and onwards. This’ll show you that it’s indeed possible to collapse a Prism region.

<ContentControl x:Name="ActionContent" prism:RegionManager.RegionName="{x:Static inf:RegionNames.ActionRegion}">
  <ContentControl.Template>
    <ControlTemplate TargetType="ContentControl">
      <Grid>
        <Controls:RoundedBox />
        <ContentPresenter Margin="10,0,10,0" Content="{TemplateBinding Content}" />
      </Grid>
      <ControlTemplate.Triggers>
        <Trigger Property="HasContent" Value="false">
          <Setter Property="Visibility" Value="Collapsed" />
        </Trigger>
      </ControlTemplate.Triggers>
    </ControlTemplate>
  </ContentControl.Template>
</ContentControl>

They combine this with a data converter that is being made use of within the row definitions of a grid layout:

<Grid.Resources>
  <StockTraderRI:VisibilityToStarHeightConverter x:Key="VisibilityToStarHeightConverter" />
</Grid.Resources>
<Grid.Rows>
  …
  <RowDefinition Height="{Binding Visibility, ElementName=ActionContent, Converter={StaticResource VisibilityToStarHeightConverter}, ConverterParameter=5}" />
  …

where the converter itself is defined as

public class VisibilityToStarHeightConverter : IValueConverter {
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
    if ((Visibility)value == Visibility.Collapsed) {
      return new GridLength(0, GridUnitType.Star);
    } else {
      if (parameter == null) {
        throw new ArgumentNullException("parameter");
      }
      return new GridLength(double.Parse(parameter.ToString(), culture), GridUnitType.Star);
    }
  }
…

I’ve omitted a couple of things here, but the picture is clear: you don’t actually need to make use of the zindex or other workarounds.

Again, as mentioned above, the implementation I pasted here is not mine, but part of the Prism Quick Starts over at Microsoft.