different screen and different view - win-universal-app

I want to have a different view with different screen in UWP, For example I have a grid with three columns in UWP app, inside the three columns it has two textboxes and button or other control. I want to change the Grid's column and row based on the screen size. When the screen size is more than 1000, the grid will have one row with three columns . when is more than 600 it will have two row, or it will have three row.

In UWP app, if you want to show different content/view based on the different screen size, we can use the AdaptiveTrigger to implement the adaptive UI.
The AdaptiveTrigger class has only two parameters: MinWindowWidth and MinWindowHeight. These two parameters allow us to switch state of window based on the different screen size.
For the detailed information, please check:
https://blogs.msdn.microsoft.com/cdndevs/2015/06/26/uwp-new-features-of-visual-state-manager-part-1/ .
In order to implement your scenario, I have created the following example, please try to refer to:
<Grid Background="Gray">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="ThreeColumns">
<VisualState.Setters>
<Setter Target="MyTextBox1.(Grid.Column)" Value="0"></Setter>
<Setter Target="MyTextBox1.(Grid.Row)" Value="0"></Setter>
<Setter Target="MyTextBox2.(Grid.Column)" Value="1"></Setter>
<Setter Target="MyTextBox2.(Grid.Row)" Value="0"></Setter>
<Setter Target="MyButton.(Grid.Column)" Value="2"></Setter>
<Setter Target="MyButton.(Grid.Row)" Value="0"></Setter>
<Setter Target="MyButton.Content" Value="This is one Row"></Setter>
</VisualState.Setters>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1000"></AdaptiveTrigger>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="TwoColumns">
<VisualState.Setters>
<Setter Target="MyTextBox1.(Grid.Column)" Value="0"></Setter>
<Setter Target="MyTextBox2.(Grid.Row)" Value="0"></Setter>
<Setter Target="MyTextBox1.(Grid.Column)" Value="1"></Setter>
<Setter Target="MyTextBox2.(Grid.Row)" Value="0"></Setter>
<Setter Target="MyButton.(Grid.Column)" Value="0"></Setter>
<Setter Target="MyButton.(Grid.Row)" Value="1"></Setter>
<Setter Target="MyButton.Content" Value="This is Two Row"></Setter>
</VisualState.Setters>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600"></AdaptiveTrigger>
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Height="500">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Name="MyTextBox1" Grid.Row="0" Height="50"></TextBox>
<TextBox Name="MyTextBox2" Grid.Row="1" Height="50"></TextBox>
<Button Name="MyButton" Background="Red" Content="This is Three Row" Grid.Row="2" Height="50"></Button>
</Grid>
The result:

Related

Show icon on SecondaryCommands (UWP)

I set the icons in my SecondaryCommand of CommandBar but aren't shown. Why?
<CommandBar RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignVerticalCenterWithPanel="True" Margin="0">
<CommandBar.SecondaryCommands>
<AppBarButton Name="shareButton" Label="Condividi" x:Uid="condividi" Click="shareButton_Click" Icon="ReShare" />
<AppBarButton Name="contactButton" Icon="Contact" x:Uid="contatti" Label="Contatti" Click="contactButton_Click" />
</CommandBar.SecondaryCommands>
</CommandBar>
They are not shown because of the default AppBarButton template. You will need to modify it.
Just follow these steps:
Temporarily put an AppBarButton in the CommandBar.PrimaryCommands collection.
Right click the button in the designer and click on Edit Template > Edit a Copy...
In the dialog that opens enter a name for your style, e.g. MyAppBarButtonStyle
Set this style to your secondary buttons:
<CommandBar.SecondaryCommands>
<AppBarButton Name="shareButton" Label="Condividi" x:Uid="condividi" Icon="ReShare" Style="{StaticResource MyAppBarButtonStyle}" />
<AppBarButton Name="contactButton" Icon="Contact" x:Uid="contatti" Label="Contatti" Style="{StaticResource MyAppBarButtonStyle}" />
</CommandBar.SecondaryCommands>
Modify the style to your liking.
By default the following elemnt is used in the overflow menu:
<TextBlock x:Name="OverflowTextLabel" Foreground="{TemplateBinding Foreground}" FontSize="15" FontFamily="{TemplateBinding FontFamily}" HorizontalAlignment="Stretch" Margin="12,0,12,0" Padding="0,5,0,7" TextAlignment="Left" TextWrapping="NoWrap" Text="{TemplateBinding Label}" TextTrimming="Clip" Visibility="Collapsed" VerticalAlignment="Center"/>
You might want to replace it with something like that:
<StackPanel x:Name="OverflowContentRoot" Orientation="Horizontal" Visibility="Collapsed" MinHeight="{ThemeResource AppBarThemeCompactHeight}">
<ContentPresenter x:Name="OverflowContent" AutomationProperties.AccessibilityView="Raw" Content="{TemplateBinding Icon}" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="Stretch" Height="20" Margin="0,14,0,4"/>
<TextBlock x:Name="OverflowTextLabel" Foreground="{TemplateBinding Foreground}" FontSize="15" FontFamily="{TemplateBinding FontFamily}" HorizontalAlignment="Stretch" Margin="12,0,12,0" Padding="0,5,0,7" TextAlignment="Left" TextWrapping="NoWrap" Text="{TemplateBinding Label}" TextTrimming="Clip" VerticalAlignment="Center"/>
</StackPanel>
You will also need to modify the overflow visual state to display your new template:
<VisualState x:Name="Overflow">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ContentRoot">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="OverflowContentRoot">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
And increase the button width:
<Setter Property="Width" Value="150"/>
Of course, you'll want to further modify the template to your liking, but this should at least get you going.
Damir's answer somehow put me on the right track and after spending a stupid amount of time on this, I eventually found out a solution that's simple.
Note that it may not suit everyone as the buttons don't get highlighted when hovering over with your mouse but it's the closest and easiest way I've figured out on how to do it on a UWP solution
First define a ControlTemplate in your Styles.xaml or your Page.Resources as such:
<ControlTemplate x:Key="SecondaryCommandTemplate" TargetType="AppBarButton">
<Grid x:Name="Root" Background="{TemplateBinding Background}">
<Grid x:Name="ContentRoot" HorizontalAlignment="Stretch" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" VerticalContentAlignment="Center"
VerticalAlignment="Stretch" x:Name="Content"
AutomationProperties.AccessibilityView="Raw" Content="{TemplateBinding Icon}"
Foreground="{TemplateBinding Foreground}" HorizontalAlignment="Stretch"
Height="20" Margin="7,0,7,0"/>
<TextBlock Grid.Column="1" VerticalAlignment="Center" x:Name="TextLabel"
Foreground="{TemplateBinding Foreground}" FontSize="12"
FontFamily="{TemplateBinding FontFamily}" TextAlignment="Left"
TextWrapping="Wrap" Text="{TemplateBinding Label}"/>
</Grid>
</Grid>
</ControlTemplate>
Then simply define the Template your SecondaryCommands:
<CommandBar.SecondaryCommands>
<AppBarButton Label="Settings"
Icon="Setting"
Command="{Binding CommandBarViewModel.SettingsCommand}"
Template="{StaticResource SecondaryCommandTemplate}"/>
<AppBarButton Label="Admin"
Icon="Admin"
Command="{Binding CommandBarViewModel.SettingsCommand}"
Template="{StaticResource SecondaryCommandTemplate}"/>
</CommandBar.SecondaryCommands>
It's a simple as that! What I don't get is that after following Damir's suggestion, and examining the XAML style that was generated for the button, I ended up removing all the visual states and I noticed that both my icon and text were displayed!! Why?? I don't understand why would Microsoft want to hide the icon in the SecondaryCommands and I'll be honest, I didn't spot the specific code that actually did it. Once I removed all the VisualStates, I noticed I was left with a template and then it was just a case of adding a grid and playing around with VerticalAlignment, HorizontalAlignment and 'Margin'.
Hope this helps!
Here's a much simpler, less elegant, way to do it. It works because most UWP icons are glyphs of the Segoe MDL2 Assets Font included in Windows.
Look up the Unicode point for the symbol you want from Microsoft's
Segoe MDL2 Assets
Guide
(eg. E702 for the Bluetooth icon, E72D for the Share icon).
Use something like UnicodeMap to
show that letter on screen. Don't worry that it looks like a blank
square, it'll work in your app.
Copy the character into your XAML as below, making sure to set the FontFamily of your AppBarButton to Segoe MDL2 Assets.
<CommandBar.SecondaryCommands>
<AppBarButton FontFamily="Segoe MDL2 Assets" Label=" Help"/>
<AppBarButton FontFamily="Segoe MDL2 Assets" Label=" Update database"/>
</CommandBar.SecondaryCommands>
And this is what you'll get.
I use this technique in an app that's localised to Russian and Chinese with no problems.
Well its pretty easier than this, use the reference microsoft.midiGmDls in your proyect and it's done.

How do I cascade Styles in a Universal Windows Platform app?

I am yet again struggling with UWP. It seems that I am unable to cascade Styles within Styles. Is this something else that is not allowed in UWP?
This is what I am trying to do...
<Style x:Key="MainMenuRadioButtonStyle" TargetType="RadioButton">
<Setter Property="Backgroud" Value="Grey"/>
<Style.Resources TargetType="TextBlock">
<Setter Property="Margin" Value="12,0,0,0"/>
</Style.Resources>
</Style>
However, VS2015 complains that the <Style.Resources> is invalid. I do not want to have to individually style the TextBlock within my RadioButton's content.
Cascading within styles not supported in UWP (or XAML in general). What you usually do is split up re-usable styles/properties and reference those.
<Thickness x:Key="MyMargin">"12,0,0,0"</Thickness>
<Style x:Key="MainMenuRadioButtonStyle" TargetType="RadioButton">
<Setter Property="Background" Value="Grey"/>
<Setter Property="Margin" Value="{StaticResource MyMargin}" />
</Style>
What you try to achieve is 'alter' the template of a RadioButton. You can find the full template here: https://msdn.microsoft.com/en-us/library/windows/apps/mt299147.aspx. If you dig into the template, you'll see this piece of code:
<ContentPresenter x:Name="ContentPresenter"
Content="{TemplateBinding Content}"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Grid.Column="1"
AutomationProperties.AccessibilityView="Raw"
TextWrapping="Wrap" />
This is the part that's showing the actual content of your RadioButton and as you can see it's not a TextBlock, but a ContentPresenter (which will show text as if it was a TextBlock). The good news is that this control has a Margin property, which takes the value of the Padding property from the template. So to achieve what you want, you can simple fill in this property:
<Style x:Key="MainMenuRadioButtonStyle" TargetType="RadioButton">
<Setter Property="Background" Value="Grey"/>
<Setter Property="Padding" Value="{StaticResource MyMargin}" />
</Style>
If you want to change properties that are not available in the default template, then you'll have to create your own template.

Make HubSection fill screen height

I am creating an application where I use the Hub control, in one of the HubSections I have a Bing Maps MapView. I would like to have that to fill the entire height of the screen, just like with a Hero HubSection, where you just set the HubSection.Background to an ImageBrush.
Now I could probably tweak the MapView Margin and get a dirty and approximate solution to this, but I am not sure if this would work on all screen sizes.
This is what I have now:
This is what I would like:
Do you have any ideas how this can be achieved?
The default HubSection template contains a Grid which divides the Hub's height into three rows:
A placeholder for the Hub's Header
The HubSection's Header
The HubSection's Content
If you want a HubSection to display differently you can apply a customized template.
In the designer open the document outline window and right click on a HubSection. Choose the Edit Template.Edit a Copy... menu. This will create a new HubSectionStyle with a copy of the template.
In the Xaml editor find the template (VS will drop you right there) and scroll down to the bottom where you'll see something like:
<Grid HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Rectangle x:Name="HubHeaderPlaceholder" Grid.Row="0"/>
<Button x:Name="HeaderButton" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" FontWeight="{ThemeResource HubSectionHeaderThemeFontWeight}" FontSize="{ThemeResource HubSectionHeaderThemeFontSize}" Margin="{ThemeResource HubSectionHeaderThemeMargin}" Grid.Row="1" Template="{StaticResource HeaderButtonTemplate}"/>
<ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Grid.Row="2"/>
</Grid>
You can edit this to match your needs. The ContentPresenter will contain the HubSection's DataTemplate, so if you want it to start from the top you can change it from Grid.Row 2 to Grid.Row 0 and Grid.RowSpan 3. You could also remove the HeaderButton and HubHeaderPlaceHolder and compress the Grid down if you don't need them, remove the Margin or set Padding to 0, etc.
<Grid HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>

Grid with lots of information - do not show when empty

I have a very large grid, where I am showing some of my XAML below, but it should not show the Textblockes on the row, if the value is empty.
How can I create that?
<Grid x:Name="JobDetailGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" x:Uid="JobDetailTaskType" />
<TextBlock Grid.Row="0" Grid.Column="2" x:Uid="JobDetailTaskTypeSrv" Text="{Binding TaskType}" />
<TextBlock Grid.Row="1" Grid.Column="0" x:Uid="JobDetailStatus" />
<TextBlock Grid.Row="1" Grid.Column="2" x:Uid="JobDetailStatusSrv" Text="{Binding Status}" />
<TextBlock Grid.Row="4" Grid.Column="0" x:Uid="JobDetailApproved" />
<TextBlock Grid.Row="4" Grid.Column="2" x:Uid="JobDetailApprovedSrv" Text="{Binding Approved}" />
Perhaps I could do it in C#, but I am thinking, if I could make a Binding or create a StackPanel, but the problem with StackPanel as I see it, is that I need to create margin after each TextBlock
Or do I need to create my own User-Control for this purpose?
This can easily be done via binding! You need to create a converter that will take a string, and return a visibility (so empty string will hide the text box), then set the visibility of the textblock as follows:-
<TextBlock Grid.Row="0" Grid.Column="0" x:Uid="JobDetailTaskType" Visibility={Binding TaskType, Converter={StaticResource visibilityConverter}}/>
Place the visibility on both the textblock's (the label and the value), and since you have the height to auto you shouldn't need to mess about with margins.

How to get the text in list box to be right aligned?

My ListBox is databound to 2 fields. The first is left aligned which is fine, the problem is with the second one which has to be right aligned. I tried using TextAlignment ="Right" and also HorizontalAlignment="Right", none of them worked.
Here is a sample code:
<ListBox x:Name="_listBox">
<ListBox.DataTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,4,8,0">
<TextBlock Text="{Binding Path=ContainerNumber}" />
<TextBlock TextAlignment="Right" Text="{Binding Path=Content}"/>
</StackPanel>
</DataTemplate>
</ListBox.DataTemplate>
Any ideas?
Add to the StackPanel markup:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Margin="0,4,8,0">
This problem is that the StackPanel isn't using all the width available because it is by default aligned Left horizontally.
EDIT: Alternatively you need to style ListBoxItems:
<ListBox.Resources>
<Style x:Key="{x:Type ListBoxItem}" TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
</ListBox.Resources>
Hope this helps.

Resources