Pivot control customization on UWP - c#

Basically I need to customize the pivot control on my uwp app and I use the style of pivot from windows phone 8.1. And it looks like this eventually(the yellow part is the content of the pivot item, I just use color to differentiate the header and the content)
But right now it does not meet the require of the original design. So I have two questions here:
1.How do I limit user flick the pivot in one direction? For example, users could only flick the control from left to right because the yellow content part will move to left and cover the header if the pivot is flicked from the right to the left. The content, which is the yellow part, will move entirely along with your finger and the other covered pivot header will be shown because the yellow part moves away, as you can see on the image. This is the reason why I care about the swiping direction because if you swipe left, the yellow part will covers part of the header before the gesture is done(which is not showing up in the image).
2.How to change the foreground color of the unselected pivotitem header? Right now as you can see, during the flicking process, the yellow content part will move away and the unselected header will be shown. That looks weird and it is not a good design at all. The unselected header is suppose to be transparent or be the same as the background color of the page.
Here is the code of the style:
<Style x:Key="PivotStyle1" TargetType="Pivot">
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Foreground" Value="{ThemeResource PivotForegroundThemeBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Pivot">
<Grid x:Name="RootElement" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Orientation">
<VisualState x:Name="Portrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" Storyboard.TargetName="TitleContentControl">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource PivotPortraitThemePadding}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Landscape">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" Storyboard.TargetName="TitleContentControl">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource PivotLandscapeThemePadding}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl x:Name="TitleContentControl" ContentTemplate="{TemplateBinding TitleTemplate}" Content="{TemplateBinding Title}" Style="{StaticResource PivotTitleContentControlStyle}"/>
<ScrollViewer x:Name="ScrollViewer" HorizontalSnapPointsAlignment="Center" HorizontalSnapPointsType="MandatorySingle" HorizontalScrollBarVisibility="Hidden" Margin="{TemplateBinding Padding}" Grid.Row="1" Template="{StaticResource ScrollViewerScrollBarlessTemplate}" VerticalSnapPointsType="None" VerticalScrollBarVisibility="Disabled" VerticalScrollMode="Disabled" VerticalContentAlignment="Stretch" ZoomMode="Disabled">
<PivotPanel x:Name="Panel" VerticalAlignment="Stretch">
<PivotHeaderPanel x:Name="Header">
<PivotHeaderPanel.RenderTransform>
<CompositeTransform x:Name="HeaderTranslateTransform" TranslateX="0"/>
</PivotHeaderPanel.RenderTransform>
</PivotHeaderPanel>
<ItemsPresenter x:Name="PivotItemPresenter">
<ItemsPresenter.RenderTransform>
<TranslateTransform x:Name="ItemsPresenterTranslateTransform" X="0"/>
</ItemsPresenter.RenderTransform>
</ItemsPresenter>
</PivotPanel>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And the XAML code for the pivot control:
<Pivot Style="{StaticResource PivotStyle1}">
<Pivot.HeaderTemplate>
<DataTemplate>
<Grid Height="auto">
<Grid.RowDefinitions>
<RowDefinition Height="21*"/>
<RowDefinition Height="299*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="19*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding}"
Margin="14,50,9,-120"
Grid.Row="1"
HorizontalAlignment="Center"
FontSize="48"
FontFamily="ms-appx:NotoSansCJKsc-Black.otf#Noto Sans CJK SC"
TextWrapping="Wrap"
LineStackingStrategy="BlockLineHeight"
LineHeight="49" Width="48"
Height="auto"/>
</Grid>
</DataTemplate>
</Pivot.HeaderTemplate>
<PivotItem Header="评论" Margin="83,-47,0,0" Background="Yellow">
<Grid>
<ListView x:Name="listview" d:LayoutOverrides="TopPosition, BottomPosition" ItemTemplate="{StaticResource GroupTemplate}" ItemsSource="{Binding Groups}" Margin="10,0,0,0"/>
</Grid>
</PivotItem>
<PivotItem Header="转发" Margin="93,-47,0,0" Background="Yellow">
<Grid>
<ListView x:Name="listview2" d:LayoutOverrides="TopPosition, BottomPosition" ItemTemplate="{StaticResource GroupTemplate}" ItemsSource="{Binding Groups}"/>
</Grid>
</PivotItem>
</Pivot>

For your first question, you have customize the style of the Pivot control, your gesture shown above works fine on the mobile emulator, but not on the local machine. This is the problem about ManipulationMode in the design of a Pivot control. Pivot control's Gesture is achieved inside it's style, so it is possible to manipulate it in one direction, but we need to find the key point in the style.
You can use Manipulation to do this. You can modify your style of Pivot control like this:
<PivotPanel x:Name="Panel" VerticalAlignment="Stretch">
<PivotHeaderPanel x:Name="Header" ManipulationMode="None">
<PivotHeaderPanel.RenderTransform>
<CompositeTransform x:Name="HeaderTranslateTransform" TranslateX="0" />
</PivotHeaderPanel.RenderTransform>
</PivotHeaderPanel>
<ItemsPresenter x:Name="PivotItemPresenter" ManipulationMode="None">
<ItemsPresenter.RenderTransform>
<TranslateTransform x:Name="ItemsPresenterTranslateTransform" X="0" />
</ItemsPresenter.RenderTransform>
</ItemsPresenter>
</PivotPanel>
and use this Pivot control like this:
<Pivot Style="{StaticResource PivotStyle1}" x:Name="myPivot" ManipulationMode="TranslateX" ManipulationStarting="OnStarting" ManipulationCompleted="OnCompleted">
...
</Pivot>
And the code behind:
public double pointx1;
private void OnCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
var pointx2 = Window.Current.CoreWindow.PointerPosition.X;
if (pointx2 > pointx1)
{
if (myPivot.SelectedIndex == 0)
myPivot.SelectedIndex = 1;
else
myPivot.SelectedIndex = 0;
}
else
return;
}
private void OnStarting(object sender, ManipulationStartingRoutedEventArgs e)
{
pointx1 = Window.Current.CoreWindow.PointerPosition.X;
}
Here is also a workaround method to solve this problem, consider that there is no manipulation in the style of Pivot, you can achieve this using PointerPoint you can modify your style of Pivot control like this:
<PivotPanel x:Name="Panel" VerticalAlignment="Stretch" ManipulationMode="None">
<PivotHeaderPanel x:Name="Header">
<PivotHeaderPanel.RenderTransform>
<CompositeTransform x:Name="HeaderTranslateTransform" TranslateX="0" />
</PivotHeaderPanel.RenderTransform>
</PivotHeaderPanel>
<ItemsPresenter x:Name="PivotItemPresenter">
<ItemsPresenter.RenderTransform>
<TranslateTransform x:Name="ItemsPresenterTranslateTransform" X="0" />
</ItemsPresenter.RenderTransform>
</ItemsPresenter>
</PivotPanel>
and use this Pivot control like this:
<Pivot Style="{StaticResource PivotStyle1}" PointerReleased="OnPointerExited" PointerPressed="OnPointerPressed" x:Name="myPivot">
...
</Pivot>
And the code behind:
public PointerPoint pointer1;
private void OnPointerExited(object sender, PointerRoutedEventArgs e)
{
var pointer2 = e.GetCurrentPoint(myPivot);
var position1x = pointer1.Position.X;
var position2x = pointer2.Position.X;
if (position2x > position1x)
{
if (myPivot.SelectedIndex == 0)
myPivot.SelectedIndex = 1;
else
myPivot.SelectedIndex = 0;
}
else
return;
}
private void OnPointerPressed(object sender, PointerRoutedEventArgs e)
{
pointer1 = e.GetCurrentPoint(myPivot);
}
And for your second question, as #ganchito55 said, you can modify the style of PivotHeaderItem.
Update:
If you just don't want to see the header of the other item when you manipulate it, you can modify the PivotHeaderItem like this:
......
<Setter Property="FontWeight" Value="{ThemeResource PivotHeaderItemThemeFontWeight}" />
<Setter Property="CharacterSpacing" Value="{ThemeResource PivotHeaderItemCharacterSpacing}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Transparent" />
<Setter Property="Padding" Value="{ThemeResource PivotHeaderItemMargin}" />
<Setter Property="Height" Value="48" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="IsTabStop" Value="False" />
......

Related

UWP Change SplitView.Pane content according to button clicked

In UWP I'm trying to create a SplitView on the left side of the screen with four buttons, any of the first three buttons open the pane but show different content according to which button was clicked: 1st = preferences, 2nd = account, 3rd = info about program. The 4th button simply closes the pane back to its original state. My question is how do I go about showing different content in the pane according to the button clicked? Is there maybe a better control for this?
Content when the first button is clicked
Content when the second button is clicked
Content when the third button is clicked
Right now each content simply has a different header but I plan to add things like a theme changer in the preferences content, account information in the user content and info related to the program in the info content.
XAML Code:
<Grid>
<SplitView IsPaneOpen="False"
DisplayMode="CompactInline"
CompactPaneLength="50"
OpenPaneLength="250">
<SplitView.Pane>
<StackPanel Orientation="Horizontal">
<StackPanel x:Name="ButtonPanel"
Background="Goldenrod">
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="FontSize"
Value="25">
</Setter>
<Setter Property="Width"
Value="50">
</Setter>
<Setter Property="Height"
Value="50">
</Setter>
<Setter Property="Foreground"
Value="Black">
</Setter>
<Setter Property="Background"
Value="Transparent">
</Setter>
</Style>
</StackPanel.Resources>
<Button x:Name="PreferencesButton"
Content="☰"
Click="PreferencesButton_Click">
</Button>
<Button x:Name="UserButton"
FontFamily="Segoe MDL2 Assets"
Content=""
Click="UserButton_Click">
</Button>
<Button x:Name="InfoButton"
Content="🛈"
Click="InfoButton_Click">
</Button>
<Button x:Name="CloseButton"
FontFamily="Segoe MDL2 Assets"
Content=""
Click="CloseButton_Click">
</Button>
</StackPanel>
<StackPanel x:Name="ContentPanel">
<!-- Add content based on which button was clicked -->
</StackPanel>
</StackPanel>
</SplitView.Pane>
<SplitView.Content>
<Grid>
<TextBlock Text="SplitView Basic"
FontSize="54"
Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center">
</TextBlock>
</Grid>
</SplitView.Content>
</SplitView>
</Grid>
Update:
You can create three UserControls to add different contents and add these UserControls in your ContentPanel. When you click the Button, show the corresponding content and hide other UserControls. You can use VisualStateManager or in code-behind to switch different contents. For example:
.xaml:
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Account">
<VisualState.Setters>
<Setter Target="Per.Visibility" Value="Collapsed"/>
<Setter Target="MyAccount.Visibility" Value="Visible"/>
<Setter Target="MyInformation.Visibility" Value="Collapsed"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Preferences">
<VisualState.Setters>
<Setter Target="Per.Visibility" Value="Visible"/>
<Setter Target="MyAccount.Visibility" Value="Collapsed"/>
<Setter Target="MyInformation.Visibility" Value="Collapsed"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Information">
<VisualState.Setters>
<Setter Target="Per.Visibility" Value="Collapsed"/>
<Setter Target="MyAccount.Visibility" Value="Collapsed"/>
<Setter Target="MyInformation.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SplitView x:Name="MySplitView"
IsPaneOpen="False"
DisplayMode="CompactInline"
CompactPaneLength="50"
OpenPaneLength="250">
<SplitView.Pane>
<StackPanel Orientation="Horizontal">
......
<StackPanel x:Name="ContentPanel">
<!-- Add content based on which button was clicked -->
<local:PerUserControl x:Name="Per" Visibility="Collapsed"></local:PerUserControl>
<local:AccountUserControl x:Name="MyAccount" Visibility="Collapsed"></local:AccountUserControl>
<local:InfoUserControl x:Name="MyInformation" Visibility="Collapsed"></local:InfoUserControl>
</StackPanel>
</StackPanel>
</SplitView.Pane>
<SplitView.Content>
......
</SplitView.Content>
</SplitView>
</Grid>
.cs:
private void PreferencesButton_Click(object sender, RoutedEventArgs e)
{
MySplitView.IsPaneOpen = true;
VisualStateManager.GoToState(this, "Preferences", true);
// Or manually hide or show UserControls
//Per.Visibility = Visibility.Visible;
//MyAccount.Visibility = Visibility.Collapsed;
//MyInformation.Visibility = Visibility.Collapsed;
}
private void UserButton_Click(object sender, RoutedEventArgs e)
{
MySplitView.IsPaneOpen = true;
VisualStateManager.GoToState(this, "Account", true);
}
private void InfoButton_Click(object sender, RoutedEventArgs e)
{
MySplitView.IsPaneOpen = true;
VisualStateManager.GoToState(this, "Information", true);
}

Create Custom Control with Storyboard XAML

I created a custom Control in a Windows 10 Universal App project, which is containing a Storyboard. The Code of the storyboard is looking like this:
<Storyboard x:Key="StatisticUpdateAnnimation">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(RingSlice.EndAngle)" Storyboard.TargetName="ringSlice">
<EasingDoubleKeyFrame KeyTime="0" Value="45"/>
<EasingDoubleKeyFrame KeyTime="0:0:2.2" Value="{Binding Angle}">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseIn"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
As you can see the x:Key = "StatisticUpdateAnnimation, the storyboard should be triggered only manually in C# code so I do not know how to Play this Storyboard after I created the Custom User Control in the Mainpage file like this:`
local:ProgressRing x:Name="Progress" Margin="7" VerticalAlignment="Top" HorizontalAlignment="Center" Tapped="ProgressRing_Tapped"/>
The style is like this
<Style TargetType="local:RingPresenter" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:RingPresenter">
<Grid>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Mode=TwoWay, ElementName=Representor, Path=EndAngle}" FontFamily="Vladimir Script" FontSize="48"></TextBlock>
<helper:RingSlice InnerRadius="100" Radius="150" StartAngle="0" EndAngle="{TemplateBinding Angle}" Fill="DarkCyan" x:Name="ringSlice">
</helper:RingSlice>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I access my storyboard?
Since I don't know what is your ProgressRing.HelperClasser, here I wrote a sample to show one method using Storyboard inside of the CustomControl. As we know, CustomControl is template control inside of the ResourceDictionary, we can for example use Storyboard inside of the ControlTemplate like this:
Generic.xaml
<Style TargetType="local:ProgressRing">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ProgressRing">
<Grid x:Name="RootGrid">
<Grid.Resources>
<Storyboard x:Key="std">
<ColorAnimation Storyboard.TargetName="brush" Storyboard.TargetProperty="Color"
Duration="0:0:2" From="LightBlue" To="Red" AutoReverse="True" />
</Storyboard>
</Grid.Resources>
<Ellipse Width="100" Height="100">
<Ellipse.Fill>
<SolidColorBrush x:Name="brush" />
</Ellipse.Fill>
</Ellipse>
<TextBlock Text="111" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And in the cs file of this Custom control:
public ProgressRing()
{
this.DefaultStyleKey = typeof(ProgressRing);
this.Loaded += ProgressRing_Loaded;
}
private void ProgressRing_Loaded(object sender, RoutedEventArgs e)
{
StoryboardPlay();
}
public void StoryboardPlay()
{
var rootGrid = this.GetTemplateChild("RootGrid") as Grid;
var std = rootGrid.Resources["std"] as Storyboard;
std.Begin();
}
I played this Storyboard here once it is loaded. Here the Control.GetTemplateChild method is useful, it helps find the named element in the instantiated ControlTemplate visual tree. Then you can get the resource inside this element.
Now if you use this custom control like this:
<local:ProgressRing x:Name="Progress" Margin="7" VerticalAlignment="Top" HorizontalAlignment="Center" Tapped="ProgressRing_Tapped" />
<Button VerticalAlignment="Bottom" Content="Click to play storyboard" Click="Button_Click" />
Now you can get the storyboard to play like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
Progress.StoryboardPlay();
}

Set Dimensions of RelativePanel's Children proportional to that of parent view

I am new to Windows Runtime programming and decided to get stuck in ahead of the release of Windows 10.
I am trying to design an adaptive page UI that looks something like as follows,
There is header "stuff" at the top and beneath it I want two columns, each with a textblock header and below it, a listview. The listview could be arbitraryheight and so the parent of the two blocks should, I think, be a scrollviewer.
On mobile however, this UI won't work as the screen is far to narrow, and so I would like to use a visualstate to rearrange the page so it looks as follows,
As you can see, the need for a scrollviewer is apparent to wrap this section. the "Other stuff" at the top should stay fixed however so it can be seen all the time.
I have tried a number of approaches to achieve this but haven't been able to manage it. What I currently have is this:
//.... Other Stuff ......
<ScrollViewer x:Name="SummaryScrollViewer" Grid.Row="2" HorizontalScrollBarVisibility="Disabled"
HorizontalScrollMode="Disabled" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto" HorizontalContentAlignment="Center">
<RelativePanel x:Name="SummaryRelativePanel">
<Grid x:Name="lCol" Width="{Binding ActualWidth, ElementName=SummaryRelativePanel}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="lcolHead" Grid.Row="0" Text="TextBlock:"/>
<ListView x:Name="lcolList" Grid.Row="1">
</ListView>
</Grid>
<StackPanel x:Name="rCol" Orientation="Vertical" RelativePanel.RightOf="lCol">
<TextBlock x:Name="rcolHead" Text="TextBlock:"/>
<ListView x:Name="rcolList" Height="Auto">
</ListView>
</StackPanel>
</RelativePanel>
</ScrollViewer>
As you can see, I have tried to make the contents of each column both a stackpanel, and a grid, but I haven't been able to set the width of them to be, in "desktop view", half that of the containing relative panel, which should fill the full width of the screen, and in "mobile view" they should fill the full width of the parent.
I have found answers on how to bind the width to the ActualWidth property of the parent element as can be seen in the snippet, and this works, but I can't seem to make the two columns fill half of the parent each.
I wanted to use a RelativePanel so I can use the viewstate to change the properties of the right hand column to be either RightOf="LeftCol" or Below="LeftCol", and the widths should then be updated too to fill the width required.
Using a grid Should also be possible, define a 4x4 grid where in desktop the bottom two are collapse, or in mobile the right two are collapsed, but I was under the impression that this is the precise usecase the relativepanel was intended for.
In all examples of relativepanel they use relativepanel to move programmer defined with/height elements such as rectangles RelativePanel class.
It would also be possible to manually set ActualWidth of each column programatically from the code-behind but I don't know how to query which visual state the app/page is currently in to figure out how wide and where each column should be.
Any help and advice on what the "best" way to achieve such a thing would be would be greatly appreciated.
Here we go, let's begin that the bugs (or things I think are bugs)
1.- If I set a control with binding to the RelativePanel ActualWidth it just takes the first time, I mean, if I expand the window the control does not resize, so bug?
So let's do it with Grid:
<Grid x:Name="LayoutRoot" Background="Red" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowSizeStates" >
<VisualState x:Name="SmallScreen" >
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ContentLayoutRoot.Background" Value="Green"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[0].Height" Value="100"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[1].Height" Value="400"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[2].Height" Value="100"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[3].Height" Value="400"/>
<Setter Target="ContentLayoutRoot.ColumnDefinitions[0].Width" Value="1*"/>
<Setter Target="ContentLayoutRoot.ColumnDefinitions[1].Width" Value="0"/>
<Setter Target="SubHeaderOneLayout.(Grid.Row)" Value="0"/>
<Setter Target="ContentOneLayout.(Grid.Row)" Value="1"/>
<Setter Target="SubHeaderTwoLayout.(Grid.Row)" Value="2"/>
<Setter Target="ContentTwoLayout.(Grid.Row)" Value="3"/>
<Setter Target="SubHeaderTwoLayout.(Grid.Column)" Value="0"/>
<Setter Target="ContentTwoLayout.(Grid.Column)" Value="0"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="WideScreen">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1000" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ContentLayoutRoot.Background" Value="Purple"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[0].Height" Value="100"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[1].Height" Value="900"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[2].Height" Value="0"/>
<Setter Target="ContentLayoutRoot.RowDefinitions[3].Height" Value="0"/>
<Setter Target="ContentLayoutRoot.ColumnDefinitions[0].Width" Value="0.5*"/>
<Setter Target="ContentLayoutRoot.ColumnDefinitions[1].Width" Value="0.5*"/>
<Setter Target="SubHeaderOneLayout.(Grid.Row)" Value="0"/>
<Setter Target="ContentOneLayout.(Grid.Row)" Value="1"/>
<Setter Target="SubHeaderTwoLayout.(Grid.Row)" Value="0"/>
<Setter Target="ContentTwoLayout.(Grid.Row)" Value="1"/>
<Setter Target="SubHeaderTwoLayout.(Grid.Column)" Value="1"/>
<Setter Target="ContentTwoLayout.(Grid.Column)" Value="1"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid x:Name="HeaderLayout" VerticalAlignment="Top" Height="32">
<TextBlock Text="Other Stuff" HorizontalAlignment="Center"/>
</Grid>
<ScrollViewer Grid.Row="1">
<Grid x:Name="ContentLayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="900"/>
<RowDefinition Height="0"/>
<RowDefinition Height="0"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="SubHeaderOneLayout" >
<TextBlock Text="Sub Header One" HorizontalAlignment="Center"/>
</Grid>
<Grid x:Name="SubHeaderTwoLayout" Grid.Column="1">
<TextBlock Text="Sub Header Two" HorizontalAlignment="Center"/>
</Grid>
<Grid x:Name="ContentOneLayout" Background="Orange" Grid.Row="1">
<TextBlock Text="ContentOne Layout" HorizontalAlignment="Center"/>
</Grid>
<Grid x:Name="ContentTwoLayout" Background="Orange" Grid.Row="1" Grid.Column="1">
<TextBlock Text="ContentOne Layout" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</ScrollViewer>
I could try to make it with Relative Panel but involves events, and more things, tell me if it is enough.
And, well the triggers I discovered by myself, you can get more info in my article in codeproject

Windows store app - XAML - One style with different images

I've been looking at a blog that contains some info about having styles for app bar buttons. Below is one of the styles i edited slightly.
<Page.Resources>
<ResourceDictionary>
<Style x:Key="TasksButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="9"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" To="White" Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="ButtonEllipse" />
<ColorAnimation Duration="0" To="Black" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="Glyph" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel Orientation="Vertical">
<Grid Margin="0,14,0,5" >
<Ellipse x:Name="ButtonEllipse" Height="40" Width="40" Fill="Transparent" HorizontalAlignment="Center"
Stroke="#FF00A5E7" StrokeThickness="2" VerticalAlignment="Center"/>
<Image x:Name="ButtonImage" Source="/Assets/Image1.png" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<TextBlock Text="{TemplateBinding Content}" HorizontalAlignment="Center"
FontFamily="Segoe UI" FontSize="12"/>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Page.Resources>
I want to use this style many times though I'm unsure if there is way I can change the image source of this line
<Image Source="/Assets/Image1.png" HorizontalAlignment="Center" VerticalAlignment="Center"/>
without simply just copying a pasting the entire style.
I want to do something like this. (I've tried it but it doesn't appear to be valid)
Pseudo XAML
<Button x:Uid="appbarOne" Click="NavButton_Click" Tag="Client.Pages.one" Style="{StaticResource TasksButtonStyle ButtonImage.Source="Assets/Image1"}" Content="Tasks"/>
<Button x:Uid="appbarTwo" Click="NavButton_Click" Tag="Client.Pages.two" Style="{StaticResource TasksButtonStyle ButtonImage.Source="Assets/Image2"}" Content="Tasks"/>
<Button x:Uid="appbarThree" Click="NavButton_Click" Tag="Client.Pages.three" Style="{StaticResource TasksButtonStyle ButtonImage.Source="Assets/Image3"}" Content="Tasks"/>
<Button x:Uid="appbarFour" Click="NavButton_Click" Tag="Client.Pages.four" Style="{StaticResource TasksButtonStyle ButtonImage.Source="Assets/Image4"}" Content="Tasks"/>
Is there a way i can do this using something similar to Style="{StaticResource TasksButtonStyle ButtonImage.Source="Assets/Image4"}"?
Replace <Image /> in custom style with this.
<Image x:Name="ButtonImage" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="None"
Source="{Binding Path=(local:AppBarButton.Image),RelativeSource={RelativeSource TemplatedParent}}"/>
Remove below line from style as there is no element named "Glyph"
<ColorAnimation Duration="0" To="Black" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="Glyph" />
Add a class named AppBarButton with below given definition. It has one attached property Image. We will use that to provide image source from button tag to button style.
public class AppBarButton
{
public static string GetImage(DependencyObject obj)
{
return (string)obj.GetValue(ImageProperty);
}
public static void SetImage(DependencyObject obj, string value)
{
obj.SetValue(ImageProperty, value);
}
public static readonly DependencyProperty ImageProperty =
DependencyProperty.RegisterAttached("Image", typeof(string), typeof(AppBarButton), new PropertyMetadata(string.Empty));
}
Now in you XAML page add buttons like this,
<StackPanel>
<Button Style="{StaticResource TasksButtonStyle}" local:AppBarButton.Image="ms-appx:///Assets/Screenshot_2.png" />
<Button Style="{StaticResource TasksButtonStyle}" local:AppBarButton.Image="ms-appx:///Assets/Screenshot_3.png" />
<Button Style="{StaticResource TasksButtonStyle}" local:AppBarButton.Image="ms-appx:///Assets/Screenshot_4.png" />
</StackPanel>
Here local refers to namespace of class AppBarButton. For my case it's
<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">
Because I declared AppBarButton class in App2 namespace.
you can use put the styles in a new xaml file say globalstyles.xaml.
then refer the xaml file in you page as below,
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Styles.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
once the styles have been referred in the Page you can use the style as below
<Button Name="cancel" Content="cancel" Style="{StaticResource CancelButtonStyle}"
HorizontalAlignment="Right" Margin="5,45,5,7" />
<Button Name="Submit" Content="Submit" Style="{StaticResource SubmitButtonStyle}"
HorizontalAlignment="Right" Margin="5,45,5,7" />
Hope this helps.
You can define a template that will use an attached property. In code, add a new class for the attached property:
public class AssociatedObject
{
public static ImageSource GetImage(DependencyObject obj)
{
return (ImageSource)obj.GetValue(ImageProperty);
}
public static void SetImage(DependencyObject obj, ImageSource value)
{
obj.SetValue(ImageProperty, value);
}
// Using a DependencyProperty as the backing store for Image. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ImageProperty =
DependencyProperty.RegisterAttached("Image", typeof(ImageSource), typeof(AssociatedObject), new PropertyMetadata(null));
}
Then, in your template, do a TemplateBinding to the parent object (removing most of the style for brevity):
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
// REMOVED A BUNCH HERE
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="3">
<Grid>
// YOUR IMAGE IS HERE
<Image Source="{TemplateBinding local:AssociatedObject.Image}" Stretch="None"/>
<ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</Border>
</ControlTemplate>
// REMOVED A BUNCH HERE
</Setter.Value>
</Setter>
</Style>
Look at the Image element in the Grid. It contains a TemplateBinding to the parent. Then, when you instantiate your button in XAML, you simply need to say what the AssociatedObject.Image is set to:
<Button Style="{StaticResource ButtonStyle1}" local:AssociatedObject.Image="/assets/Logo.scale-100.png"></Button>
If you want the look of an appbar button, you should look at the AppBarButton class instead which has everything for you. You can then use the Icon property to use one of the 200+ built-in icon styles or provide your own through the PathIcon, SymbolIcon or BitmapIcon classes as well.
See: http://timheuer.com/blog/archive/2013/10/29/use-new-appbarbutton-in-windows-8-1-commandbar.aspx

disabling all clicks for a short period after clicking a image

I'm using multiple images to create something like a virtual keyboard. I wish to add a short period of time after a image is clicked, where at the short period of time, all clicks on images are disabled. Does any1 knows how to do it? Here's my code for one of the images.
<Button Grid.Column="2" Command="{Binding Path=PressAndRelease}" CommandParameter="Q" Style="{StaticResource TransparentButton}" Effect="{Binding}">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image Name="imgNormalQ" Source="/wa;com/Images/alp/q.png" Height="127"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Panel.ZIndex" Value="999"/>
<Setter TargetName="imgPressedQ" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
in Silverlight I have done this using VisualStateManager
there is not much difference in WPF
edited
I have created sample Storyboard to disabled WPF UIElement.
<StackPanel>
<Border x:Name="MainContent">
<StackPanel x:Name="ButtonPanel">
<Button Width="100" Click="AnyButton_Click">Busy State 1</Button>
<Button Width="100" Click="AnyButton_Click">Busy State 2</Button>
<Button Width="100" Click="AnyButton_Click">Busy State 3</Button>
</StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="BusyStates">
<VisualState x:Name="Ready" />
<VisualState x:Name="Busy">
<Storyboard>
<BooleanAnimationUsingKeyFrames Duration="0"
Storyboard.TargetName="ButtonPanel"
Storyboard.TargetProperty="IsEnabled">
<DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
<Button Width="100" x:Name="ClearButton" Click="ClearButton_Click">Ready</Button>
</StackPanel>
the VisualState named "Busy" will animate ButtonPanel.IsEnabled = false (at keytime=0)
here's basic code behind
private void AnyButton_Click(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToElementState(MainContent, "Busy", true);
}
private void ClearButton_Click(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToElementState(MainContent, "Ready", true);
}
PS. if you follow the MVVM. VisualStateManager responsible for View. it should be part of XAML not ViewModel

Categories

Resources