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>
Related
I've got a mockup with a screen I don't know how to implement properly:
I'm wondering how to position that Login button (and the "sign in with" block). Without "Login", it would be quite easy with a StackLayout. But this makes it less easy and I'm searching for a simple solution.
I presume it's feasible with an AbsoluteLayout with position calculations in the codebehind, but that makes the whole page more complicated than it looks.
The white block is a Frame that's used everywhere in the app. It's not specific to the login page, so I want to reuse it elsewhere.
How would you do that?
I think you can use a Grid... with 3 rows.
Rows 1 and 2 have the same height.
"Login data" (User/pwd...) occupy row 0 and 1
Button occupy row 2 and 2
For Example
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="fev_ventilazione_smartwatch.Pages.MyPageTest">
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="8*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="4*" />
</Grid.ColumnDefinitions>
<Label Text="TEXT" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="3" BackgroundColor="Aqua"/>
<Button Text="BUTTON" Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" BackgroundColor="Fuchsia"/>
</Grid>
</ContentPage.Content>
</ContentPage>
Produce
I presume it's feasible with an AbsoluteLayout with position
calculations in the codebehind, but that makes the whole page more
complicated than it looks.
Yes you are right. It is feasible with AbsoluteLayout. But its not as complicated as it seems.
Construct your basic elements first:
White container/StackLayout for login details
Login Button.
Facebook/Google buttons in a horizontal StackLayout.
"OR" Label
"Create An Account" Button
Put them in AbsoluteLayout and define their AbsoluteLayout.LayoutFlags as well as AbsoluteLayout.LayoutBounds.
Now key here is to understand that how Absolute Layout works?
You can find that out from this page: Absolute Layout
I have wrote some code to achieve something similar below. But make sure you learn it fully and understand everything before you can use it in your app:
<ContentPage.Content>
<ScrollView BackgroundColor="Silver">
<AbsoluteLayout Margin="30" >
<StackLayout BackgroundColor="White" HeightRequest="150" Spacing="20" Padding="10" VerticalOptions="FillAndExpand"
AbsoluteLayout.LayoutBounds="0,0,1,250" AbsoluteLayout.LayoutFlags="XProportional,YProportional,WidthProportional"
>
<Entry Text="Login" HeightRequest="30"/>
<Entry Text="Password" HeightRequest="30" IsPassword="true" />
<Label Text="FORGOT YOUR PASSOWORD?" HorizontalTextAlignment="End"/>
</StackLayout>
<Button
Text="LOGIN"
FontAttributes="Bold"
BackgroundColor="Maroon"
TextColor="White"
HeightRequest="70"
WidthRequest="70"
AbsoluteLayout.LayoutBounds=".5,215,70,70" AbsoluteLayout.LayoutFlags="XProportional" BorderRadius="35"
/>
<StackLayout
Orientation="Horizontal"
HorizontalOptions="EndAndExpand"
AbsoluteLayout.LayoutBounds="1,270,0.5,70" AbsoluteLayout.LayoutFlags="XProportional,WidthProportional"
>
<Button Text="Facebook"/>
<Button Text="Google"/>
</StackLayout>
<Label Text="OR" HorizontalTextAlignment="Center"
AbsoluteLayout.LayoutBounds="0.5,350,50,50"
AbsoluteLayout.LayoutFlags="XProportional"
/>
<Button
Text="CREATE AN ACCOUNT" Margin="15"
BackgroundColor="White" TextColor="Maroon"
BorderColor="Maroon" BorderWidth="1"
BorderRadius="0"
HorizontalOptions="FillAndExpand"
AbsoluteLayout.LayoutBounds="0.5,370,1,150"
AbsoluteLayout.LayoutFlags="XProportional,WidthProportional"
/>
</AbsoluteLayout>
</ScrollView>
</ContentPage.Content>
And here is the result:
NOTE: You can achieve the same look using RelativeLayout as well.
Hope this helps.
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.
When implementing and the Hamburger Menu pane opens, the bottom part (Setting) is covered/hidden by the BottomAppBar.
Solution:
Simply add another grid row to your page and implement a CommandBar there:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<... Grid.Row="0"/>
<... Grid.Row="1"/>
<CommandBar Grid.Row="2"/>
</Grid>
I am pleased to tell you that a Template 10 sample project demonstrating how to implement Bottom App Bar already exists and you can review it on GitHub.
https://github.com/Windows-XAML/Template10/tree/master/Samples/BottomAppBar
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.
I'm currently trying to design a table for contact information including a column for icons like telephone, email or similar symbols and I want to align them with the text from the next column
icon | Telephone:
| +1212354567
icon | Email:
| x#y.com
Is there any Layout which can be compared in functionality to Androids RelativeLayout? I tried to work with the Grid Layout but this seems to be error prone and not exact enough. I don't want to divide my layout into columns and rows, instead I want to describe their position as it is used in RelativeLayout (toLeft, toRight, AlignParentBottom etc.).
The StackPanel can be compared to the LinearLayout, which I want to avoid as it is not suitable for my current design.
Is there any comparison between Windows Phone and Android Layouts on which I can orientate? This one is incomplete and does not give advise for the RelativeLayout.
I know you said you did not want to use a Grid but I feel that you have to in this case.
I would structure it with both a grid and stack panels though.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Image for first row item -->
<Image Grid.Column="0" Grid.Row="0" Source="icon-url" />
<!-- Container for the details of the first row item -->
<StackPanel Grid.Column="1" Grid.Row="0">
<TextBlock Text="Telephone:" />
<TextBlock Text="+1212354567" />
</StackPanel>
<!-- Image for second row item -->
<Image Grid.Column="0" Grid.Row="1" Source="icon-url" />
<!-- Container for the details of the second row item -->
<StackPanel Grid.Column="1" Grid.Row="1">
<TextBlock Text="Email:" />
<TextBlock Text="x#y.com" />
</StackPanel>
<!-- Just add rows to the grid to continue the list -->
</Grid>
There is no panel that compares, but someone that was adventurous could create one. There are many articles on how to do this, but here's one for reference. http://www.switchonthecode.com/tutorials/wpf-tutorial-creating-a-custom-panel-control
That said, there's no reason not to use Grid for what you're trying to do. It's not "error prone" or "not exact enough". SharedSizeGroup should become your friend here, though.