Fixed size of UIElement with window resizing collapse problem - c#

I'm developing an App with UWP. I have problem with UI element design.
before begin explaining my circumstance, I'll show the exact point of my App's problem.
as you can see, bottom of advertise is half-collapsed.
I tried to add HorizontalAlignment, VerticalAlignment stretch but it didn't work.
I want to make my advertise Grid has priority of the page, so it seems entirely.
I mean, more space for advertise, and less space for ListView item.
I tried to handle this situation with declaring *XAML VisualState* but It seems not enough for me. I don't want to spend my time with struggling with constant number (Height,Width`).
Struggling with this problem, I could find adaptive layout repository (C#/Xaml).
picture of app is following. githubLink
I wanted to follow that Source because it works really good. but the source include some animating part and some advanced skills, and I couldn't catch it up.
I just want to show my advertise entirely. and I want to maximize width of my advertise without any collapse and with just enough margin. and I want my advertise always be bottom of the App.
I'm sorry if you feel the question is ambiguous.
my source is below.
ShellPage.xaml
<Grid>
<Frame x:Name="shellFrame" /> <!-- navigation frame -->
</Grid>
MainPage.xaml
<Page
x:Class="nlotto_gen.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mods="using:nlotto_gen.Models"
xmlns:UI="using:Microsoft.Advertising.WinRT.UI"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Grid
x:Name="ContentArea"
Margin="{StaticResource MediumLeftRightMargin}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="reallongwst">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1200"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="adsense.Width" Value="1080"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="longwst">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="800"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="adsense.Width" Value="728"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="longhst">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="700"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="mMain_Button.(Grid.Row)" Value="1"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="shorthst">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowHeight="220"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="mMain_Button.(Grid.Row)" Value="0"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
BorderBrush="{ThemeResource AppBarBorderThemeBrush}"
x:Name="myGrid"
BorderThickness="2" >
<!--The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content.
Place your content here.-->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListView>
<!--... omitted ...-->
</ListView>
<Button Grid.Column="1" Grid.Row="1" x:Uid="Main_Button" x:Name="mMain_Button" Command="{x:Bind ViewModel.game_create}" Style="{StaticResource myButton}"/>
<UI:AdControl
Grid.Row="2"
Grid.ColumnSpan="2"
x:Name="adsense"
ApplicationId="****"
AdUnitId="test"
Width="728"
Height="80"
Margin="5, 5, 5, 5"/>
</Grid>
</Grid>
</Page>

You have to set the third Grid RowDefinition to have Auto height:
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
Auto gives the controls within the Row exactly the space they need to fit.
* works differently - Grid first calculates the space required for Auto and absolute height rows and then divides the remaining space to the "star"-based rows. So in your case the app gave the list five times more space than the ad. But when the app window is small, the space may not be enough to fit the ad as a whole.
Also, because you no longer have multiple rows with *, you can just remove the 5 from the first row's declaration.

you have 3 rows and your AdControl is in last row at the bottom so the height of third row should be Auto so just change the RowDefinitions of your grid like following :
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
You can remove all the Visual State Triggers, because you do not need responsive layout for making the ad control appear correctly.
Banner ads always have fixed size, there are multiple number of ads you can display in your app, but whatever you choose must have a fixed size. : https://learn.microsoft.com/en-us/windows/uwp/monetize/supported-ad-sizes-for-banner-ads
So you can put 2 ads in your app, one for narrow size and one for wide size and then toggle their visibility with Visual States, or another option would be to use Native Ads which blend in which the theme of your app.

Related

Different XAML Layout Structure for one CS file in UWP

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:
Until now, we have tried visual state manager, but unfortunately by using it we could only change the alignment not positions of controls.
We also checked conditional xaml but it seems it is only for version adaptability.
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>
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.

Adding a Top Navigation Bar in Windows 8 - Tutorial Issue

I am trying out a tutorial on WIndows 8. I need to add a Navigation Bar. The steps are given below;
The following is from the tutorial.
In Solution Explorer, double-click MainPage.xaml to open it.
In the Document Outline, select the "pageRoot" element.
In the Properties panel, click the Properties button () to show the Properties view.
Under Common in the Properties panel, find the TopAppBar property.
Click the New button next to TopAppBar. An AppBar control is added to the page.
In the Document Outline, expand the TopAppBar property.
Select the "photoPageButton" element, drag it onto the AppBar, and drop it.
Under Layout in the Properties panel, set the HorizontalAlignment property to Right ().
Press F5 to build and run the app. To test the app bar, right-click on the main page. The app bar opens at the top of the screen.
I Double-clicked on the MainPage.xaml, and then in the Document Outline i selected pageRoot. and in the properties Window expanded Common and i clicked on New next to TopAppBar.
It added several other Fields below it. Allow Drop, Background and Cache Mode are some of it. Then in the Document Outline i dragged the button to the AppBar under TopAddBar. Changed the HorizontalAlignment to Right, build and executed the application. But i don't see the button added to the top Navigation bar. What have i done wrong here ?
UPDATE
<Page.Resources>
<!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
<x:String x:Key="AppName">My Application</x:String>
</Page.Resources>
<common:LayoutAwarePage.TopAppBar>
<AppBar Background="#E5A41D1D" AllowDrop="True" BorderBrush="#E5C5A7A7" HorizontalAlignment="Right">
<Button Content="Next Page
" HorizontalAlignment="Right" VerticalAlignment="Stretch" Width="230" Height="70" Background="#FF12668D" FontFamily="Shruti" FontSize="36" Click="Button_Click_2"/>
</AppBar>
</common:LayoutAwarePage.TopAppBar>
<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Style="{StaticResource LayoutRootStyle}" Background="#FF282D40">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Back button and page title -->
<!-- Back button and page title -->
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="Welcome !!! " Style="{StaticResource PageHeaderTextStyle}" Foreground="#DE2374AC"/>
</Grid>
<VisualStateManager.VisualStateGroups>
<!-- Visual states reflect the application's view state -->
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<!-- The back button and title have different styles when snapped -->
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
You're following this tutorial here, correct? It looks like you've dragged the wrong button to your TopAppBar.
The button you should be dragging is named photoPageButton (its x:Name attribute). Instead, the button you've got in your TopAppBar doesn't have a name, and presents the text "Next Page".
Your XAML markup for the TopAppBar should look something like this after you've dragged the photoPageButton to the TopAppBar:
<common:LayoutAwarePage.TopAppBar>
<AppBar HorizontalAlignment="Right">
<Button x:Name="photoPageButton" Content="Go to photo page"/>
</AppBar>
</common:LayoutAwarePage.TopAppBar>
After you get a little farther in the tutorial and apply a style to the button, your markup for the TopAppBar will then look like this:
<common:LayoutAwarePage.TopAppBar>
<AppBar HorizontalAlignment="Right">
<Button x:Name="photoPageButton"
Click="photoPageButton_Click"
HorizontalAlignment="Right"
Style="{StaticResource PicturesAppBarButtonStyle}"/>
</AppBar>
</common:LayoutAwarePage.TopAppBar>
It's perfectly acceptable to have the other AppBar settings in there as well - Background, BorderBrush; these are harmless changes to the color - and AllowDrop defaults to true, I believe, so that's fine too.

Modified Data Binding

I'm creating a transition effect that will slide 2 panels (side to side).
My plan is to have a Grid that has the width of the window multiplied by 2 through data-binding, divide it by 2 to have the 2 panels, then put Grids in them (so I'll have 2 panels equally divided with their own grid and you can see only one of them at a time. all it takes now is to move the root grid with an animation to create the transition effect).
So I'm trying to data bind the Grid's width to the width of the window multiplied by 2 (as I've written in bold above), but I have no idea how you can modify a data bind, and let it keep updating accordingly. so if possible - how do you do it?
I guess I could do it with events (just like in any other .NET application) but that's just more opportunities for bugs to come and fester (i.e. events I'll miss); so I'd really appreciate a good and clean solution.
By the way, if you have a better way to make the transition, please let me know in the comments. My mind is still open to ideas.
Thanks!
I've done it. It was like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="0" />
<Grid x:Name="Panel1" />
<Grid x:Name="Panel2"/>
</Grid>
Now, this is side-scrolling, however the point is same. All you do is apply RenderTransform.TranslateTransform animation to Panel2, you animate X from 0 to Panel2 Width, essentially it will be completely off, and after that you just set Panel2 Column to "1".
I can give you tomorrow little code example too, but you can get started.
Here is the Xaml that takes care of slide2slide animation when user toggles the button.
<Grid.Triggers>
<EventTrigger RoutedEvent="ToggleButton.Checked" SourceName="workingPlanButton">
<BeginStoryboard>
<Storyboard Completed="Storyboard_Completed">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:0.1"
Duration="0:0:00.5"
Storyboard.TargetName="lsView"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)"
Timeline.DesiredFrameRate="30">
<LinearDoubleKeyFrame KeyTime="00:00:00.3" Value="{Binding ElementName=bodyGrid, Path=ActualHeight}" />
</DoubleAnimationUsingKeyFrames>
<!-- Hide the panel -->
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0.5"
Storyboard.TargetName="lsView"
Storyboard.TargetProperty="Visibility"
Timeline.DesiredFrameRate="30">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Hidden}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
Now the actual grid:
<Grid x:Name="bodyGrid" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="1" />
</Grid.RowDefinitions>
<StudyPlan:StudyPlanControl />
<local:LessonControl x:Name="lsView />
<local:LessonControl.RenderTransform>
<TranslateTransform Y="0" />
</local:LessonControl.RenderTransform>
</local:LessonControl>
</Grid>

Unable to make scrollviewer scroll horizontally

I have a ScrollViewer that contains a StackedPanel with rectangles laid out horizontally. I want to be able to scroll horizontally, but this isn't happening for me. Here is my XAML:
<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="BlastSwing.GroupedItemsPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BlastSwing"
xmlns:data="using:BlastSwing.Data"
xmlns:common="using:BlastSwing.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<!--
Collection of grouped items displayed by this page, bound to a subset
of the complete item list because items in groups cannot be virtualized
-->
<CollectionViewSource
x:Name="groupedItemsViewSource"
Source="{Binding Groups}"
IsSourceGrouped="true"
ItemsPath="TopItems"
d:Source="{Binding AllGroups, Source={d:DesignInstance Type=data:SampleDataSource, IsDesignTimeCreatable=True}}"/>
</Page.Resources>
<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Back button and page title -->
<TextBlock x:Name="pageTitle" Text="Blast Swing" Style="{StaticResource PageHeaderTextStyle}" Margin="40,0,-10,53"/>
<ScrollViewer HorizontalAlignment="Left" Height="628" Grid.Row="1" VerticalAlignment="Top" Width="1366" RenderTransformOrigin="0.476999998092651,0.998000025749207" VerticalScrollMode="Disabled" Margin="-22,0,0,0" HorizontalScrollMode="Auto">
<StackPanel Height="568" Width="1313" RenderTransformOrigin="-0.0179999992251396,0.512000024318695" Orientation="Horizontal">
<Rectangle Fill="#FF974B55" Height="568" Stroke="Black" VerticalAlignment="Top" Width="371"/>
<Rectangle Fill="#FF17179C" Height="568" Stroke="Black" VerticalAlignment="Top" Width="371"/>
<Rectangle Fill="#FF8D2B80" Height="568" Stroke="Black" VerticalAlignment="Top" Width="371"/>
<Rectangle Fill="#FF301D2F" Height="568" Stroke="Black" VerticalAlignment="Top" Width="371"/>
<Rectangle Fill="#FFF4F4F5" Height="568" Stroke="Black" VerticalAlignment="Top" Width="371"/>
</StackPanel>
</ScrollViewer>
<!-- Back button and page title -->
<!-- Horizontal scrolling grid used in most view states -->
<!-- Vertical scrolling list only used when snapped -->
<VisualStateManager.VisualStateGroups>
<!-- Visual states reflect the application's view state -->
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
<VisualState x:Name="FullScreenPortrait"/>
<!--
The back button and title have different styles when snapped, and the list representation is substituted
for the grid displayed in all other view states
-->
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</common:LayoutAwarePage>
You are setting Scrollviewer's Width="1366" which is more than your child stackpanel Width="1313".
If you want to see the horizontal scrollbar then you might want to set the size of ScrollViewer less than 1313 and it should be able to display the horizontal scrollbar as it is not able to display the content fully.
Set the HorizontalScrollBarVisibility property on the ScrollViewer to Visible or Auto.
You are setting the Width of your StackPanel manually and it is less than the total of its children.

Paper fold animation in windows phone 7

Hi I am developing an animation in which flip animation is required as shown in http://www.avatar-app.com/dev/2012/01/24/ios-flip-transform/ (Similar to weatherflow app in wp7). Now I am successful in achieving this by making use of two border one above the other and animating one border using planeprojection. And here is my code
<Grid x:Name="ContentPanel" Background="Wheat" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
<Storyboard x:Name="myStoryboard">
<DoubleAnimation Storyboard.TargetName="planeProjection" Storyboard.TargetProperty="RotationX" From="0" To="90" Duration="0:0:5" />
</Storyboard>
</Grid.Resources>
<Border Background="AliceBlue" Grid.Row="0" ManipulationStarted="Border_ManipulationStarted">
<Border .Projection>
<PlaneProjection x:Name="planeProjection" CenterOfRotationY="1"/>
</Border .Projection>
</Border>
<Border Background="Aqua" Grid.Row="1">
</Border>
</Grid>
The problem is, here I am using two controls(Border), but I want to use animation on only one control i.e dividing the animation so that it applies to half part of the control(only one border)?
Guys help me.

Categories