Different XAML Layout Structure for one CS file in UWP

Viewed 54

We need to create 4 different .xaml layouts for same .cs in our UWP application. Structure of those layouts depends on the value "questionType" which comes from db.

Each variation of layout should contain same controls but in different positions.(i.e each variation should contain one image, one richTextEditor and radioGroup that consist 4 radios)

For instance if questionType=1, image should be positioned on the left side of the screen, if questionType=2, then it should be positioned on the top of rich text editor and also radios should be positioned horizontally...

Things that we have already considered and tried:

  1. Until now, we have tried visual state manager, but unfortunately by using it we could only change the alignment not positions of controls.

  2. We also checked conditional xaml but it seems it is only for version adaptability.

  3. Panels with changing visibility. But we decided not to go with this solution because it is very ugly.

Anyone who will direct us to the right direction, will be appreciated.

Thanks.

Edit:

<VisualState x:Name="Layout1">
       <Storyboard>
         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.HorizontalAlignment)"
           Storyboard.TargetName="ContentRoot">
           ...             
         </ObjectAnimationUsingKeyFrames>          
       </Storyboard>
     </VisualState> 
1 Answers

VisualStateManager can change whatever property you define on an element, not just Alignments.

For the sake of simplicity, I use two Borders to represent the Image and the RichTextBox. Initially the Image is positioned to the left, and then I use VisualStateManager to go to another visual state, in which the Image is positioned to the top. Note that the properties (Grid.Column) and (Grid.Row) are changed just like (FrameworkElement.HorizontalAlignment)

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" /> 
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" /> 
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Border x:Name="imageControl"
            Background="Red"
            Height="200" Width="200"
            Grid.Row="1" />
    <Border x:Name="richTextBoxControl"
            Background="Green"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch"
            Grid.Row="1" Grid.Column="1" />

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="Layout1" />
            <VisualState x:Name="Layout2">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames
                        Storyboard.TargetName="imageControl"
                        Storyboard.TargetProperty="(Grid.Column)">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="1" />
                    </ObjectAnimationUsingKeyFrames>    
                    <ObjectAnimationUsingKeyFrames
                        Storyboard.TargetName="imageControl"
                        Storyboard.TargetProperty="(Grid.Row)">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="0" />
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>            
    </VisualStateManager.VisualStateGroups>
</Grid>    

And in code behind, change the VisualState based on the value questionType.

if (questionType == 1) 
   return; //Layout1 is the default state
else if (questionType ==  2)
    VisualStateManager.GoToState(this, "Layout2", true);                         

There are alternative ways, like using a StackPanel to host the controls, initially horizontally oriented, and change it to vertically oriented in the other visual state.

Related