I'm making an UAP Windows 10 App. Like app News from Microsoft, i'm trying to put the CommandBar in top on the page in desktop view, and in bottom of the page in mobile view.
How could I do this ? I think I have an independant <CommandBar xxx> with empty <Page.TopAppBar> and <Page.BottomAppBar>. And depending of the size of the view, I attach the CommandBar to TopAppBar or BottomAppBar... ?
Having ideas ? Thanks you.
You can use the VisualState class to adjust alignment of things depending on the size of the screen, using the StateTriggers property. Here's some documentation about the class including some sample code here https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.visualstate.statetriggers.aspx
This sample code demonstrates the use: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlStateTriggers
Simple implementation:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<!--VisualState to be triggered when window width is >=720 effective pixels.-->
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="myPanel.VerticalAlignment" Value="Bottom" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="myPanel" VerticalAlignment="Top">
<TextBlock Text="This is a block of text for an example. "
Style="{ThemeResource BodyTextBlockStyle}"/>
</StackPanel>
(that's this example but with the values changed for your situation. https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.visualstate.statetriggers.aspx)
Related
When styling controls that have a ContentPresenter (like GridViewItem), and it has a bunch of visual states like Focused, Unfocused, PointerFocused, Disabled etc. Is there a proper way to pass the active visual state down through to the DataTemplate? IOW, is there a nice way for any UI in the DataTemplate to react to the same visual states as its parent (GridViewItem as an example, but would want a solution for any ControlTemplate that uses a ContentPresenter really)? Ex)
<DataTemplate>
<UserControl>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<!-- These states are copied from the ControlTemplate,
but obviously don't work by default. -->
<VisualState x:Name="Focused" />
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="foo.Fill" Value="Red" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="foo" />
</Grid>
</UserControl>
</DataTemplate>
My initial naive approach would be to extend ContentPresenter and add a custom property like ActiveVisualState then call VisualStateManager.GoToState((Control)contentPresentorChild, ActiveVisualState, true);. Then use that presenter in the GridViewItem template style (or whatever control I was styling). But I feel like there should be a better, more natural and not so specific, way to achieve this.
We cannot see where you put your ContentPresenter and we also cannot see where you modified your template. So it's not clear what you want.
But if your simply want to modify a property value based on different state. why not just change the status from the setter like this:
<VisualState.Setters>
<Setter Target="NameofYourContentPresenter.(UIElement.Opacity)"
Value="0.5" />
</VisualState.Setters>
For customized property you just need to specify it from your XAML.
I'm porting a Wp81 app to UWP, and it seems that the Hub layout strategy changed and it's no longer adapting HubSections width to stretch it (almost) to the width of the screen. How can I achieve that in UWP without setting absolute width on HubSections?
Details about my use case:
In my HubSection, I have an Image, that instead of being shrunk to screen width (almost - so that the next section is visible) it stretches to its native width. The same happens with TextBlock. It seems that in UWP HubSection doesn't have Width or MaxWith set according to screen width.
The purpose of a hub is to allow the user to discover stuff. So the section is not stretched to full screen by default. For you case, you'd better try with Pivot control.
Here is a design guideline for Pivot and Hub.
Besides, if you still want to use Hub and want the style to adapt to different screen size, below is a simple solution by VisualStateManager:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Phone" >
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="HeroImg.Width" Value="100" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Tablet" >
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="HeroImg.Width" Value="800" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Hub Header="News" >
<HubSection Header="Hero" x:Name ="HeroImg" >
<HubSection.Background>
<ImageBrush ImageSource="Assets/circle_hero.jpg" Stretch="UniformToFill"/>
</HubSection.Background>
</HubSection>
</Hub>
</Grid>
So, I've just started working again with Windows apps and there are a few things that I can't get working as I want (probably because I coulnd't find any sample and Channel9 videos didn't cover my case).
Starting from this article, I decided that the "reposition" technique is the one that fits my app when moving from a big screen to a smaller one.
What I did is using a StackPanel and changing its orientation using two AdaptiveTriggers (one for 0 width and another one for 720, based on the table here).
This kinda works but there are some issues that I'll illustrate with some ugly paint-edited screenshots.
This is what happens when I'm in the BigScreen situation, where there's enough space to have both A and B on the same row. The problem here is that B should take the full remaining width, covering all the blue part.
The second issue is related to resizing. When there's not enough space, the green part gets cut instead of being resized (you can see that the right border disappeared). This didn't happen before using the StackPanel to make the layout responsive.
Finally, when we are in the SmallScreen situation, orientation changes to be vertical and we have the same problem as the first one: green part's height doesn't fill the screen.
Here's the XAML used for the page:
<Page
x:Class="Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WifiAnalyzerFinal.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mvvm="using:Mvvm"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SmallScreen">
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="StackPanel.Orientation"
Value="Vertical"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="BigScreen">
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="StackPanel.Orientation"
Value="Horizontal"/>
<Setter Target="Rect.Width"
Value="200"/>
<Setter Target="Rect.Height"
Value="Auto"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel Orientation="Vertical"
Background="Blue"
x:Name="StackPanel">
<Rectangle Fill="Red"
Height="50"
x:Name="Rect"
Width="Auto"/>
<ListView ItemsSource="{Binding Stuff}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Green"
Width="Auto"
BorderBrush="DarkGreen"
BorderThickness="5"
Padding="5">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0,0,0,5"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</StackPanel>
</Grid>
</Page>
Please note that without the StackPanel the green part fits the page as it should, covering all the available area. Unfortunately I couldn't came up with a better solution because there's no sample telling us how this technique should be implemented. I also tried using the new RelativePanel but it seems that the AdaptiveTrigger's Setter doesn't work with attached properties like RelativePanel.RightOf.
Is there someone who's been successful is applying this technique without having to use code-behind?
EDIT:
I got this working using a Grid with 2 rows and 2 columns, with the AdaptiveTrigger moving all the content from row to column and viceversa.
It is possible to change RelativePanel attached property values through setters. The syntax goes like this:
<Setter Target="SomeXAMLObject.(RelativePanel.RightOf)" Value="SomeOtherXAMLObject" />
Why don't you try to use grid (instead of StackPanel) and define rows using proportional dimensions like:
`<Grid>
<Grid.RowDefinitions>
<RowDefinition width="2*"/>
<RowDefinition width="3*"/>
<RowDefinition width="1*"/>
</Grid.RowDefinitions>
</Grid>`
I added a ProgressBar to my application and I wanted it to have a transparent background, so I did it like this:
<ProgressBar IsIndeterminate="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<ProgressBar.Background>
<SolidColorBrush Color="Black" Opacity="0.5" />
</ProgressBar.Background>
</ProgressBar>
And in the Preview Window everything looks fine, however, when I run my app, the Background is simply not there. The solution I found to this is to put the ProgressBar in a Grid and set the Background property in the Grid, but since the Preview shows it right, and the property is there, shouldn't it work?
UPDATE:
Based on #Chris W. suggestion, I tried to override the default style of the ProgressBar element, like so:
<ProgressBar IsIndeterminate="True" Background="#FF000000" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="50">
<ProgressBar.Style>
<Style TargetType="ProgressBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Indeterminate">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="DeterminateRoot"
Storyboard.TargetProperty="Opacity"
To="0.5"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ProgressBar.Style>
</ProgressBar>
But still, no juice.
Need to get rid of two (2) StoryBoard Animations
Document Outline > Right Click Progress Bar > Edit Template -> Edit A Copy
<!--
<FadeOutThemeAnimation Storyboard.TargetName="DeterminateRoot"/>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DeterminateRoot"/>
-->
And as #ricochete suggested if using Opacity = 1 change up the Z-Order of DeterminateRoot to be on top of the EllipseGrid
<Border x:Name="DeterminateRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" MinHeight="{TemplateBinding MinHeight}">
<Rectangle x:Name="ProgressBarIndicator" Fill="{TemplateBinding Foreground}" HorizontalAlignment="Left" Margin="{TemplateBinding Padding}"/>
</Border>
<Grid x:Name="EllipseGrid" Opacity="0">
<!-- ... more XAML Style -->
<Grid Background="#FFFF0000">
<ProgressBar IsIndeterminate="True" Style="{StaticResource ProgressBarStyle1}" Height="50" >
<ProgressBar.Background>
<SolidColorBrush Color="Black" Opacity="0.5"/>
</ProgressBar.Background>
</ProgressBar>
</Grid>
If you go look at the default template you'll see at the bottom of the template the Background only has a TemplateBinding in one spot for x:Name="DeterminateRoot" so that's the only place you'd see your color set from the Background property.
Then if you climb up through the Storyboard for the Indeterminate State you'll find;
<DoubleAnimation Storyboard.TargetName="DeterminateRoot"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
...and you've got your ProgressBar set to IsIndeterminate="True" so you're setting the one place that accepts the Background property to a zero opacity explicitly.
So you could go pull that animation out of the Storyboard for that state, or put in your own new object to set your thing, or just do the workaround you mentioned by just throwing it in a Border or a Grid or something and doing it that way amongst other possibilities.
You might also try (once you've fixed your opacity setting issue from the storyboard) just flipping your SolidColorBrush with Opacity into just pure hex with the Alpha Channel set as 50% opacity equivalent. Making it just;
<ProgressBar Background="#80000000" IsIndeterminate="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
Anyhow, hope this helps, Cheers!
I am trying to change the rowstyle for a datagrid to change the background color when a row is selected(not the row background but the color of the selection rectangle, which by default is a bit too shiny for my application). However the behaviour i'm seeing on applying to style to the grid is that all the rows are getting shrinked together like a folded venetian blind. This is the style that i have written:
<Style x:Key="DataGridRowStyle" TargetType="sdk:DataGridRow">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGridRow">
<sdk:DataGrid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal Selected">
<Storyboard>
<ColorAnimation
Storyboard.TargetName="ButtonBrush"
Storyboard.TargetProperty="Color"
To="Red" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</sdk:DataGrid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Can someone tell me what's going on here? tbh I havn't really understood how the visual states work and kind of just shooting in the dark.
Thanks
Checking the template for the DataGrid (check here) the background color (that blue) is hard coded in the template. When the row is selected all that happens is that a rectangle becomes visible (Opacity=1). Sadly have to say that you have to re-template the whole DataGridRow... in the provided link you'll find all you might need for this.
In the template look for some code like this:
<Rectangle x:Name="BackgroundRectangle" Grid.RowSpan="2" Grid.ColumnSpan="2" Opacity="0" Fill="#FFBADDE9"/>