Fieldset in Winrt/XAML - xaml

I need to create something in WinRT/XAML similar to an HTML fielset. http://jsfiddle.net/Sf2Vy/
Basically, I have a border and there is some text on top of the border. Where the text covers the border, I need the border to not show under the text. The background behind the border isn't a solid color so I can't just set the background color of the text. The text length is variable also.
Is there an easy way to do this?

Yeah, so, the answer is no. There is no FieldSet.
Having said that, I think you could work out a similar effect simple enough. The code below shows you a solution that could easily be wrapped in a custom user control called fieldset.
<Grid Width="500" VerticalAlignment="Center">
<!-- top fieldset thing -->
<Grid VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="BorderThickness" Value="0,5,0,0" />
<Setter Property="BorderBrush" Value="white" />
<Setter Property="Margin" Value="0,-2,0,0" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="10,-15,10,0" />
<Setter Property="FontSize" Value="30" />
</Style>
</Grid.Resources>
<Border Grid.Column="0" />
<TextBlock Grid.Column="1" Text="User Info" />
<Border Grid.Column="2" />
</Grid>
<!-- regular form fields -->
<Border BorderBrush="White" BorderThickness="5,0,5,5">
<StackPanel Margin="20">
<TextBox Header="Salutation" />
<TextBox Header="First Name" />
<TextBox Header="Middle Name" />
<TextBox Header="Last Name" />
<Button Margin="0,5,-3,0" HorizontalAlignment="Right">Save Data</Button>
</StackPanel>
</Border>
</Grid>
It looks something like this:
It's not 100% perfect - or, maybe... it is.
Best of luck!

Related

UWP FlyOut template acting differently on different systems

I have a custom template for a flyout, and it works fine on about half of our systems, but it completely breaks on the other half.
Here's what the menu looks like when it works:
And here's what it looks like when it doesn't work... the semi-transparency is completely black, and the contents of the menu itself are completely off the screen:
You can ignore how the second screenshot is wider and how the stuff behind the menu looks different. That's just a different resolution and a different set-up, but this issue happens even when they're the same.
As noted in the picture, when the MenuFlyout appears (when I open the menu via clicking the AppBarButton), I need a semi-transparent area to appear in front of the rest of the page. This is accomplished by putting a big rectangle in the flyout's template, causing the shadow behind the flyout to be extended out over the rest of the page.
Here's the code of the button that triggers the flyout to show:
<AppBarButton
x:Name="MenuBtn"
Height="72"
Label="{StaticResource Menu}"
AllowFocusWhenDisabled="False"
Click="MenuBtn_Click"
CornerRadius="0"
Style="{StaticResource AppBarIconButtonStyle}"
TabIndex="9"
Width="72"
Margin="0,0,16,8"
Loaded="MenuBtn_Loaded"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignBottomWithPanel="False">
<AppBarButton.Flyout>
<MenuFlyout x:Name="HbgMenuFlyout" MenuFlyoutPresenterStyle="{StaticResource MenuFlyoutPresenterStyle}" Opening="MenuFlyout_Opening" Closing="HbgMenuFlyout_Closing" Closed="MenuFlyout_Closed">
<MenuFlyoutItem x:Name="SelectRoomBtn" x:Uid="HbgMenu_Select_Room" Style="{StaticResource MenuFlyoutItemStyleDark}" Click="SelectRoomBtn_Click" /> <!-- mobile only -->
<MenuFlyoutItem x:Name="PhysicianProfileBtn" x:Uid="HbgMenu_Physician_Preferences" Style="{StaticResource MenuFlyoutItemStyleDark}" Click="Physician_Preferences_Click" />
<MenuFlyoutItem x:Name="SystemSettingsBtn" x:Uid="HbgMenu_Settings" Style="{StaticResource MenuFlyoutItemStyleDark}" Click="SystemSettingsBtn_Click" />
<MenuFlyoutItem x:Name="HomeBtn" x:Uid="HbgMenu_Home" Style="{StaticResource MenuFlyoutItemStyleDark}" Click="HomeBtn_Click" />
<MenuFlyoutItem x:Name="LogoutBtn" x:Uid="HbgMenu_Logout" Style="{StaticResource MenuFlyoutItemStyleDark}" Click="LogoutBtn_Click" />
</MenuFlyout>
</AppBarButton.Flyout>
</AppBarButton>
Here's the code for the style attached to the MenuFlyout:
<Style x:Key="MenuFlyoutPresenterStyle" TargetType="MenuFlyoutPresenter">
<Setter Property="RequestedTheme" Value="Dark"/>
<Setter Property="Background" Value="Gray" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="0,0,0,0" />
<Setter Property="Padding" Value="0" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="False" />
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="False" />
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
<Setter Property="MinWidth" Value="{ThemeResource FlyoutThemeMinWidth}" />
<Setter Property="MaxWidth" Value="2000" />
<Setter Property="MinHeight" Value="{ThemeResource MenuFlyoutThemeMinHeight}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MenuFlyoutPresenter">
<controls:FlyoutGridControl />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here's the code for that control:FlyoutGridControl:
<UserControl
x:Class="CardiologyApp.Controls.FlyoutGridControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CardiologyApp.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400" >
<RelativePanel x:Name="RootGrid" HorizontalAlignment="Stretch">
<Rectangle x:Name="Shield" Width="2000" RelativePanel.AlignRightWith="MenuFlyoutPresenterScrollViewer" PointerPressed="Rectangle_PointerPressed" />
<ScrollViewer x:Name="MenuFlyoutPresenterScrollViewer"
Width="516"
RelativePanel.AlignRightWithPanel="True"
HorizontalAlignment="Right"
Background="Gray"
AutomationProperties.AccessibilityView="Raw">
<ItemsPresenter />
</ScrollViewer>
<Border x:Name="MenuFlyoutPresenterBorder"
VerticalAlignment="Stretch"
RelativePanel.Below="MenuFlyoutPresenterScrollViewer"
RelativePanel.AlignRightWithPanel="True"
Height="1000"
Background="Gray"
Width="516"
/>
</RelativePanel>
The workaround for the developers is to comment out the in the control:FlyoutGridControl.
Any suggestions on how to make the behavior consistent across systems? We're all on Windows 10 Enterprise.
MenuFlyout is not suitable for pop-up layer fixed on the right sidebar. In higher system versions, MenuFlyout is not limited by the size of the application window, which will invalidate your layout.
According to your actual display picture, SplitView should be a control that better meets your needs.
This is a simplified layout structure:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<CommandBar VerticalAlignment="Top" HorizontalAlignment="Stretch">
<AppBarButton/>
</CommandBar>
<SplitView DisplayMode="CompactOverlay" OpenPaneLength="516"
PanePlacement="Right" x:Name="AppSplitView" Grid.Row="1">
<SplitView.Pane>
<Grid>
<!--Used to display list items-->
<ListView/>
</Grid>
</SplitView.Pane>
<SplitView.Content>
<Grid>
<!--Main content display area-->
</Grid>
</SplitView.Content>
</SplitView>
</Grid>
If you want to apply the above code, you need to use ListViewItem in ListView to replace your MenuItem.
If you need to show your options, just set:
AppSplitView.IsPaneOpen = True;
For more information about SplitView and its display effect, you can check this document:
Split view

How Can I Reuse an Icon in Resources in UWP? In WPF, I'd use x:Shared=false

I am trying to create a button Style that I can use for a "Lookup" button throughout my UWP app. However, the icon only appears on the first button on the screen. I tried this solution using templates, but it is not working for me. Thanks for the help.
Code:
<Page.Resources>
<ControlTemplate x:Key="FindSymbolTemplate">
<SymbolIcon Symbol="Find" Foreground="White" />
</ControlTemplate>
<Style TargetType="Button" x:Key="LookupButton">
<Setter Property="Content">
<Setter.Value>
<ContentControl Template="{StaticResource FindSymbolTemplate}" />
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
....
<Button x:Name="tourNumLookup"
Style="{StaticResource LookupButton}"
Grid.Column="1"
Margin="10,0"
VerticalAlignment="Center" />
....
<Button x:Name="customerIdLookup"
Style="{StaticResource LookupButton}"
VerticalAlignment="Center"
Grid.Column="1"
Grid.Row="1"
Margin="10,0" />
The two buttons in the UI. Only the first has the SymbolIcon content.
#Romasz's solution absolutely works, but what if you want a lightly different Foreground on the SymbolIcon inside another Button?
Here's a potentially more flexible way that I normally go with.
First let's create a base Style that holds some default values for all the icons.
<Style x:Key="Style-Icon-Base"
TargetType="ContentControl">
<!-- If you don't specify the Foreground, it will use its ancestor's -->
<!--<Setter Property="Foreground"
Value="White" />-->
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Width"
Value="20" />
<Setter Property="Height"
Value="20" />
<Setter Property="Padding"
Value="0" />
</Style>
Then we create a new icon Style which inherits from the one above. Note within the ControlTemplate I have used TemplateBinding to make property values dynamic. TemplateBinding isn't available inside a DataTemplate.
<Style x:Key="Style-Icon-Find"
BasedOn="{StaticResource Style-Icon-Base}"
TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<!--
'cause you cannot change the size of the SymbolIcon, we insert a Viewbox here,
otherwise you don't need it.
-->
<Viewbox Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<SymbolIcon Symbol="Find"
Foreground="{TemplateBinding Foreground}" />
</Viewbox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This way you have created a highly reusable icon Style, to use it, have a look at the following Buttons:
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<Button Margin="4"
Padding="8"
BorderBrush="LightBlue">
<ContentControl Width="36"
Height="36"
Foreground="DarkCyan"
Style="{StaticResource Style-Icon-Find}" />
</Button>
<!-- Note how I defined the Foreground at the Button level and it flows down to the icon -->
<Button Foreground="DarkGoldenrod"
Margin="4">
<StackPanel Orientation="Horizontal">
<ContentControl Style="{StaticResource Style-Icon-Find}"
Width="16"
Height="16" />
<TextBlock Text="Search"
VerticalAlignment="Center"
Margin="8,0,0,0" />
</StackPanel>
</Button>
<Button Margin="4"
Padding="4">
<ContentControl Style="{StaticResource Style-Icon-Find}" />
</Button>
</StackPanel>
And they look like:
Generally UI elements can be used once (or saying different - have only one parent) - this is probably why it only works for the first button in your case. One solution may be to define DataTemplate and use it as ContentTemplate, so each button creates its own icon:
<Page.Resources>
<DataTemplate x:Key="FindTemplate">
<SymbolIcon Symbol="Find" Foreground="White" />
</DataTemplate>
</Page.Resources>
...
<Button x:Name="tourNumLookup" ContentTemplate="{StaticResource FindTemplate}"
Grid.Column="1" Margin="10,0" VerticalAlignment="Center" />
<Button x:Name="customerIdLookup" ContentTemplate="{StaticResource FindTemplate}"
VerticalAlignment="Center" Grid.Column="1" Grid.Row="1" Margin="10,0" />
You don't need to create ControlTemplate to reuse the icon. You can simply put this SymbolIcon to the resource dictionary and use as StaticResource for the buttons' Content.
<Page.Resources>
<SymbolIcon x:Key="FindSymbol" Symbol="Find" Foreground="White" />
</Page.Resources>
<Button x:Name="tourNumLookup"
Content="{StaticResource FindSymbol}"
Grid.Column="1"
Margin="10,0"
VerticalAlignment="Center" />
<Button x:Name="customerIdLookup"
Content="{StaticResource FindSymbol}"
VerticalAlignment="Center"
Grid.Column="1"
Grid.Row="1"
Margin="10,0" />
UPDATE
BTW this is possibly a bug in the UWP platform, because I tried the following code and only the first Button rendered the icon at desing time and none of the at runtime.
<Page.Resources>
<SymbolIcon x:Key="FindSymbol" Symbol="Find" Foreground="White" />
<Style TargetType="Button" x:Key="LookupButton">
<Setter Property="Content" Value="{StaticResource FindSymbol}"/>
</Style>
</Page.Resources>
<StackPanel>
<Button x:Name="tourNumLookup"
Style="{StaticResource LookupButton}"
Margin="10,0"
VerticalAlignment="Center" />
<Button x:Name="customerIdLookup"
Style="{StaticResource LookupButton}"
VerticalAlignment="Center"
Margin="10,0" />
</StackPanel>
I tried to assign the Setter's Value directly but I got the same result. And also tried with FontIcon.

How to make a Button expand to show its Text in Xamarin.Forms

I have created a Style for my Buttons but when I use longer texts, they are truncated.
This is the style:
<Style x:Key="DefaultButton" TargetType="Button">
<!--<Setter Property="WidthRequest">
<Setter.Value>
<OnIdiom x:TypeArguments="x:Double"
Phone="150"
Tablet="200" />
</Setter.Value>
</Setter>
<Setter Property="HeightRequest">
<Setter.Value>
<OnIdiom x:TypeArguments="x:Double"
Phone="70"
Tablet="100" />
</Setter.Value>
</Setter>-->
<Setter Property="BackgroundColor" Value="{StaticResource BaseColor}" />
<Setter Property="TextColor" Value="White" />
<Setter Property="HorizontalOptions" Value="CenterAndExpand" />
<Setter Property="VerticalOptions" Value="FillAndExpand" />
<Setter Property="Margin" Value="5" />
<Setter Property="FontSize">
<Setter.Value>
<OnIdiom x:TypeArguments="x:Double"
Phone="20"
Tablet="25" />
</Setter.Value>
</Setter>
</Style>
The button:
<Button Grid.Row="1"
Grid.Column="1"
Style="{DynamicResource DefaultButton}"
Text="Basic button with long text" />
This is how that button with a longer text looks:
I could set a very large HeightRequest for the button but that would be very bad practice.
What should I do about this?
In this situation I will often used a Grid with a BoxView and a Label to make up the button and then put a GestureRecognizer on the Grid. Add all of this to a custom control for easy reuse if you want.
I did the GestureRecognizer below from memory so it might need some fixing:
<Grid x:Name="BasicButtonGrid"
VerticalOptions="End">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.MinimumHeightRequest>
<OnIdiom x:TypeArguments="x:Double"
Phone="40"
Tablet="70"/>
</Grid.MinimumHeightRequest>
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="OnBasicButtonTapped"/>
</Grid.GestureRecognizers>
<BoxView BackgroundColor="Blue"
VerticalOptions="EndAndExpand"
InputTransparent="True"
Grid.Row="0"
Grid.Column="0"/>
<Label Text="Basic Button with long text"
TextColor="White"
FontSize="Medium"
Grid.Row="0"
Grid.Column="0"/>
</Grid>
You can use the LineBreakModeproperty. Here is the documentation to help you choose the most suitable mode.
https://developer.xamarin.com/api/type/Xamarin.Forms.LineBreakMode/

Assign the value of a dynamic element to another element

I have a ellipse with "width='auto'", and I want a circle, so it's not possible set "height='auto'" because if the user resize the window, the circle will be a ellipse. I've tried "Height='{Binding ElementName=TheLeft, Path=Width}'".
<Page
x:Class="App2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<!--<Ellipse x:Name="TheLeft" Fill="Pink" Grid.Column="0" Height="{Binding ElementName=TheLeft, Path=Width}" Width="auto" VerticalAlignment="Bottom"/>-->
<!-- I've set Height="200" in the uncommented element -->
<Ellipse x:Name="TheLeft" Fill="Pink" Grid.Column="0" Height="200" Width="auto" VerticalAlignment="Bottom"/>
<Rectangle Fill="Red" Grid.Column="1" RadiusX="50" RadiusY="40"/>
<Ellipse Fill="Pink" Grid.Column="2" Height="200" Width="auto" VerticalAlignment="Bottom"/>
</Grid>
</Page>
First, I am going to definitely suggest you take out the inline styling, especially since you want the same values for many of the properties for the two Ellipses.
<Style x:Key="circularEllipse" TargetType="{x:Type Ellipse"}>
<Setter Property="Fill" Value="Pink"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Height" Value="200"/>
<Setter Property="Width" Value="{Binding Path=Height, RelativeSource={RelativeSource Self}}"/>
</Style>
And then when you code the ellipse - you just need to call this style and it can be used for both of them, saving you coding time and reducing the amount of code on your layout.
<Ellipse x:Name="TheLeft" Grid.Column="0" Style="{StaticResouce circularEllipse}"/>
So, if you need to change the size of the circle, you only have to change the property in one place. Also, if you need a variant, you can use the BasedOn option and not have to redo the entire code. Such as:
<Style x:Key="circularEllipse2" TargetType="{x:Type Ellipse}" BasedOn="{StaticResource circularEllipse}">
<Setter Property="Height" Value="100"/>
</Style>
This will pick up all of the other properties from the previous style, but change the height (or any other property you may need to change)

Bug or User error? Unable to set TextBlock's VerticalAlignment property to Center

Hmmm. . . I'm losing my mind. . . or am I?
I'm creating a WPF app for some basic data entry. I'm using textblocks to label the textboxes but ran into a snag. Why can't I vertically center the textblocks? I can't change the vertical alignment at all. Regardless of what I value I set on the property, the textblocks remain at the top. I want them centered! I can change the horizontal alignment no problem.
The contents of the XAML file, including the styles, are included below.
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SL3_ContactEntry.MainPage"
Width="500"
Background="#FF99DF52">
<UserControl.Resources>
<Style x:Key="MyTextBlockStyle"
TargetType="TextBlock">
<Setter Property="FontSize"
Value="12" />
<Setter Property="Margin"
Value="2" />
<Setter Property="Width"
Value="Auto" />
<Setter Property="Height"
Value="28" />
<Setter Property="HorizontalAlignment"
Value="Right" />
<Setter Property="VerticalAlignment"
Value="Center" />
</Style>
<Style x:Key="MyTextBoxStyle"
TargetType="TextBox">
<Setter Property="FontSize"
Value="12" />
<Setter Property="Margin"
Value="2" />
<Setter Property="Width"
Value="Auto" />
<Setter Property="Height"
Value="28" />
</Style>
<Style x:Key="MyButtonStyle"
TargetType="Button">
<Setter Property="FontSize"
Value="12" />
<Setter Property="Margin"
Value="2" />
<Setter Property="Width"
Value="100" />
<Setter Property="Height"
Value="33" />
</Style>
</UserControl.Resources>
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="0.81*" />
<RowDefinition Height="0.19*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical"
Grid.Column="0"
Margin="5">
<TextBlock Name="FName"
Text="First Name"
Style="{StaticResource MyTextBlockStyle}" />
<TextBlock Name="LName"
Text="Last Name"
Style="{StaticResource MyTextBlockStyle}" />
<TextBlock Name="StreetAddress"
Text="Street Address"
Style="{StaticResource MyTextBlockStyle}" />
<TextBlock Name="City"
Text="City"
Style="{StaticResource MyTextBlockStyle}" />
<TextBlock Name="State"
Text="State"
Style="{StaticResource MyTextBlockStyle}" />
<TextBlock Name="ZipCode"
Text="Zip Code"
Style="{StaticResource MyTextBlockStyle}" />
</StackPanel>
<StackPanel Orientation="Vertical"
Grid.Column="1"
Margin="5">
<TextBox Name="txtFName"
Style="{StaticResource MyTextBoxStyle}" />
<TextBox Name="txtLName"
Style="{StaticResource MyTextBoxStyle}" />
<TextBox Name="txtStreetAddress"
Style="{StaticResource MyTextBoxStyle}" />
<TextBox Name="txtCity"
Style="{StaticResource MyTextBoxStyle}" />
<TextBox Name="txtState"
Style="{StaticResource MyTextBoxStyle}" />
<TextBox Name="txtZipCode"
Style="{StaticResource MyTextBoxStyle}" />
<Button Content="OK"
Style="{StaticResource MyButtonStyle}" />
</StackPanel>
</Grid>
</UserControl>
I am not 100% sure why it is not centering, probably has to do with the height set on the elements, but what you can do is apply a padding to the TextBlocks to get them centered with the TextBoxes.