Window UWP best practice to show desired content on app start - c#

I am currently teaching myself how to build a Windows UWP app.
My question is:
If I have an app which requires a login, how do I handle the decision if a login-form should be shown, or the actual start page of the app if the PasswordVault already has stored credentials?
Do I leave the MainPage blank and just write the logic (in the .cs-file) which decides if I navigate to the LoginPage or to the ContentPage (or whatever I will call it)?
Or is it the intention to put this logic into the App.xaml.cs?
Or is my approach totally wrong and this should be handled in a complete different way?

If you want to show hide content based on a ViewModel you could add a property to your ViewModel say IsLoggedIn
private bool isLoggedIn;
public bool IsLoggedIn
{
get { return isLoggedIn; }
set
{
isLoggedIn = value;
OnPropertyChanged("IsLoggedIn");
}
}
You could then install the WindowsStateTriggers from nuget
Once you have that installed add a reference at the top of your xaml page
xmlns:triggers="using:WindowsStateTriggers"
next using VisualStateManager you can simply show/hide content based on the IsLoggedIn property on your viewmodel. Here we target the Visibility property of the Grids
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LoginGroup">
<VisualState x:Name="LoggedIn">
<VisualState.StateTriggers>
<triggers:EqualsStateTrigger EqualTo="True" Value="{Binding Path=IsLoggedIn}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="LoggedInGrid.Visibility" Value="Visible"/>
<Setter Target="LoggedOutGrid.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="LoggedOut">
<VisualState.StateTriggers>
<triggers:EqualsStateTrigger EqualTo="False" Value="{Binding Path=IsLoggedIn}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="LoggedInGrid.Visibility" Value="Collapsed"/>
<Setter Target="LoggedOutGrid.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="LayoutRoot">
<Grid x:Name="LoggedInGrid">
</Grid>
<Grid x:Name="LoggedOutGrid">
</Grid>
</Grid>
</Grid>nter code here

You could check that the credentials are stored/valid when you're loading the application and make a decision whether to navigate to your main app page or a login page from the OnLaunched event in your App.xaml.cs

You could check out the extended splashscreen sample from the sdk: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/SplashScreen

Related

Xamarin Forms Shell flyoutitem tittle color

I want to change the color of option titles and selected option how can i do that?
The default Xamarin.Forms Project template is going to put styles like FlyoutItemLabelStyle, FlyoutItemLayoutStyle and MenuItemLayoutStyle in the Shell.Resources element of AppShell.xaml. These styles, in turn, will have many references to {StaticResource Primary} which is a color defined in the Application.Resources element of App.xaml. I would start by assessing what's happening in those places. Even if you're not using the template you can study it as an example of how to achieve your outcome.
Device Themes can adversely affect these settings
What I've noticed is that Xamarin UI elements with default transparent background color may not respond dynamically if the device is, for example, changed to dark mode. (I've definitely seen white text on an effectively-white background in dark mode). So one must pay attention to what the consequences will be when the device's visual themes change. There is an especially good training on this topic by Xamarin guru James Montemagno. I would highly recommend his YouTube video on Dynamic App Themes in Xamarin.Forms - Light, Dark, & Custom Modes
For the purpose of a basic demonstration of how to modify these themes, I have hardcoded "Magenta", "Blue" and "Green" in the default xaml which produces the colors shown in the image that follows.
<Shell.Resources>
<ResourceDictionary>
<Style Class="FlyoutItemLabelStyle" TargetType="Label">
<Setter Property="TextColor" Value="Magenta"></Setter>
</Style>
<Style Class="FlyoutItemLayoutStyle" TargetType="Layout" ApplyToDerivedTypes="True">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{x:OnPlatform UWP=Transparent, iOS=White}" />
<Setter TargetName="FlyoutItemLabel" Property="Label.TextColor" Value="Blue" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{StaticResource Primary}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style Class="MenuItemLayoutStyle" TargetType="Layout" ApplyToDerivedTypes="True">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter TargetName="FlyoutItemLabel" Property="Label.TextColor" Value="Green" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ResourceDictionary>
</Shell.Resources>

UWP VisualStateManager.GoToState Always Returns False

I am trying to use visual states to mark a TextBox input as invalid (by changing its border color to red) during input validation when a user submits a form the TextBox is a part of. I have the following code:
XAML
<Page.Resources>
<!-- Other resources omitted for brevity -->
<Flyout x:Key="NewTimeBlockFlyout">
<StackPanel>
<!-- Other stuff here omitted for brevity -->
<TextBox Margin="5"
Header="Name"
x:Name="NewTimeBlockNameTextBox">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Default"></VisualState>
<VisualState x:Name="Invalid">
<VisualState.Setters>
<Setter Target="NewTimeBlockNameTextBox.Background" Value="Red"></Setter>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</TextBox>
<!-- The rest of the form omitted for brevity -->
<Button x:Name="CreateTimeBlockButton"
Grid.Column="0"
Margin="0,0,2,0"
HorizontalAlignment="Stretch"
Tapped="CreateTimeBlockButton_Tapped">Create</Button>
</StackPanel>
</Flyout>
</Page.Resources>
Note: This is on a XAML Page. I am NOT using a custom control.
C#
private void CreateTimeBlockButton_Tapped(object sender, TappedRoutedEventArgs e)
{
// Validate the input.
if (String.IsNullOrWhiteSpace(this.NewTimeBlockNameTextBox.Text))
{
// These two lines of code confirm the visual state named "Invalid" does exist on the textbox.
//List<VisualStateGroup> m = VisualStateManager.GetVisualStateGroups(this.NewTimeBlockNameTextBox).ToList();
//List<VisualState> c = m.FirstOrDefault().States.ToList();
// Assignment to bool just used to inspect the return value for debugging.
bool did = VisualStateManager.GoToState(this.NewTimeBlockNameTextBox, "Invalid", false);
}
}
Problem
No matter what I try, the call to VisualStateManager.GoToState() is always returning false.
Things I have tried:
Here is the relevant documentation from Microsoft.
As seen in the C# code above, I have verified the visual state "Invalid" does exist, as expected, on the "NewTimeBlockNameTextBox" control.
I have seen several solutions including here, and here that suggest moving the <VisualStateManager.VisualStateGroups> tag in the XAML to outside of the TextBox, or to the root of the Page. Neither have worked for me.
I have also seen these two solutions here and here, but neither seemed relevant to my situation, as both seem to have issues related to things I am not doing.
I can reproduce your issue. You need to place <VisualStateManager.VisualStateGroups> outside the TextBox and skip status through VisualStateManager.GoToState(this, "Invalid", false); Please refer to the following code.
Xaml code:
<Page
……
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Default"></VisualState>
<VisualState x:Name="Invalid">
<VisualState.Setters>
<Setter Target="NewTimeBlockNameTextBox.BorderBrush" Value="Red"></Setter>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBox Margin="5"
Header="Name"
x:Name="NewTimeBlockNameTextBox" >
</TextBox>
<Button x:Name="CreateTimeBlockButton"
Grid.Row="1"
Margin="0,0,2,0"
HorizontalAlignment="Stretch"
Tapped="CreateTimeBlockButton_Tapped">Create</Button>
</StackPanel>
</Page>
Code behind:
private void CreateTimeBlockButton_Tapped(object sender, TappedRoutedEventArgs e)
{
bool a = VisualStateManager.GoToState(this, "Invalid", false);
}
Updated:
For using VisualStateManager.GoToState(), which always be done by changing its controltemplate.
You could right click the textbox in XAML designer, then select the option Edit a Template->Edit a Copy, here you will see the default textbox style placed in <Page.Resources> </Page.Resources> tag.
<Style x:Key="TextBoxStyle1" TargetType="TextBox">
……
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
……
<VisualStateManager.VisualStateGroups>
……
<VisualState x:Name="TestState">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="red"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter" …/>
<Border x:Name="BorderElement" …/>
……
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see, you could place custom state in its template, then you could use “VisualStateManager.GoToState(NewTimeBlockNameTextBox, "TestState", false);” to skip state.

Setter.Target give me an error with "RelativePanel.AlignHorizontalCenterWithPanel"

I am develop an UWP app, and I am using Template10.
I have an TextBlock, that in VisualStateNarrow I want it RelativePanel.AlignVerticalCenterWithPanel="True" and in NormalMinWidth I want RelativePanel.AlignHorizontalCenterWithPanel="True" but I can not do this!
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AdaptiveVisualStateGroup">
<VisualState x:Name="VisualStateNarrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="TextBlock.RelativePanel.AlignVerticalCenterWithPanel="True"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateNormal">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="TextBlock.RelativePanel.AlignHorizontalCenterWithPanel="True"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateWide">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}"/>
</VisualState.StateTriggers>
<VisualState.Setters>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
In XAML editor give me this error: "An Exception was thrown." - "Cannot resolve TargetProperty RelativePanel.AlignHorizontalCenterWithPanel on specified object."
I have many Setter.Target and they all work!
Example of my Setter.Target:
<Setter Target="TextBlock.Margin" Value="8"/>
<Setter Target="TextBlock.Width" Value="200"/>
<Setter Target="TextBlock.Height" Value="200"/>
Here is a way to create setters for adaptive triggers without writing a single line of code. Since VS provides neither IntelliSense nor error warning for writting them, this helps prevent bugs that are hard to diagnose.
Go to the States panel, click to activate the visual state that you want to add setters to. A red dot will apear next to the name of this visual state.
Once it's activated, go to the Objects and Timeline panel and select the element that you want to interact within this state. In your case, select the TextBlock element.
Go to the Properties panel, either expand the RelativePanel section or search for "relative" in the search box, once the properties come up, simply select the ones you want to change.
That's all! Feel free to check out the gif demo below too.
For attached properties you have to add brackets to in setters as follows:
Element.(Grid.Row)
Element.(ToolTipService.ToolTip)
So your code will look like this:
<Setter Target="TextBlock.(RelativePanel.AlignVerticalCenterWithPane‌​l)" Value="True" />

UWP load style on adaptive trigger

Trying to learn a fair bit about s and I got stuck on a particular subject. I want my buttons edited in size and alignment using a pre made style I have. An example:
<Button Style="{StaticResource ButtonFormat}">
</Button>
The button has a style saved in App.Xaml the style is written like this:
<Application.Resources>
<Style TargetType="Button" x:Key="ButtonFormat">
<Setter Property="Background" Value="#FF6E1400" />
<Setter Property="Margin" Value="5,5,5,5" />
</Style>
<Application.Resources>
Now, here is my dilemma:
I want to load another style that overwrites "ButtomFormat". I have been trying to experiment in VisualStatemanager to try and come up with the proper way of doing this but can't really find anything that explains enough for me on how to do it.
So in the visualstate such as below:
<VisualState x:Name="BigView" >
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="550" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!--stuff goes here-->
<!--stuff goes here-->
</VisualState.Setters>
</VisualState>
I want to ooverwrite ButtonFormat with ButtonFormatBlue as such:
<Style TargetType="Button" x:Key="ButtonFormatBlue ">
<Setter Property="Background" Value="Blue" />
<Setter Property="Margin" Value="5,5,5,5" />
</Style>
I saw someone suggesting using C# instead of visualstatemanagers but I didn't properly understand that description, is it possible to load it from the visualstatetrigger as I want or am I looking at the wrong direction?
All aids are appreciated, thank you in advance!
You cannot override a resource, but you can change the Button's style property.
You first have to give the button a name:
<Button x:Name="MyButton" Style="{StaticResource ButtonFormat}">
</Button>
And now you can use the VisualStateManager to change the Style property:
<VisualState x:Name="BigView">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="550" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="MyButton.Style"
Value="{StaticResource ButtonFormatBlue}" />
</VisualState.Setters>
</VisualState>
I saw someone suggesting using C# instead of visualstatemanagers but I didn't properly understand that description.
It means you can set a style to your Button manually in the code behind. For example, you can put your ButtonFormat and ButtonFormatBlue both in the App resource like this:
<Application.Resources>
<Style TargetType="Button" x:Key="ButtonFormat">
<Setter Property="Background" Value="#FF6E1400" />
<Setter Property="Margin" Value="5,5,5,5" />
</Style>
<Style TargetType="Button" x:Key="ButtonFormatBlue">
<Setter Property="Background" Value="Blue" />
<Setter Property="Margin" Value="5,5,5,5" />
</Style>
</Application.Resources>
Then your Button can be loaded with ButtonFormat style using StaticResource:
<Button x:Name="styleTestButton" Content="Style Sample" Style="{StaticResource ButtonFormat}"
VerticalAlignment="Bottom" Click="styleTestButton_Click" />
In the Button click event for example, you can change your Button's style as follows:
private void styleTestButton_Click(object sender, RoutedEventArgs e)
{
var ButtonFormatBlue = Application.Current.Resources.FirstOrDefault(r => r.Key.ToString() == "ButtonFormatBlue");
styleTestButton.Style = ButtonFormatBlue.Value as Style;
}
Or you can totally define a new style in the code behind and set this style to Button using C# in the code behind:
private void styleTestButton_Click(object sender, RoutedEventArgs e)
{
var dynamicStyle = new Style();
dynamicStyle.TargetType = typeof(Button);
dynamicStyle.Setters.Add(new Setter(BackgroundProperty, Colors.Blue));
dynamicStyle.Setters.Add(new Setter(MarginProperty, new Thickness(5, 5, 5, 5)));
styleTestButton.Style = dynamicStyle;
}
Need to know that as #MZetko said, we can't override a resource, this is why we created a new one.
is it possible to load it from the visualstatetrigger as I want or am I looking at the wrong direction?
Yes it's possible, but it's hard to tell whether you looked at the wrong direction, it depends on different scenarios. For example, if your UIElements are in the DataTemplate, then it doesn't work with StateTriggers, data binding is the best solution for this scenario. You can refer to the Remarks of VisualStateManager class, it shows perfect details of using VisualStateManager.

Long List Selector with item tap animation

I am working on Windows Phone 8, i have long list selector with few items in it.When i tap on the items i need to add some animation to it like, move the text in and come back.How to achieve this? i am trying to apply the same to list box as well.
I have tried this :
<Style x:Key="LongListSelectorStyle1" TargetType="phone:LongListSelector">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<UserControl>
<Border x:Name="MyBorder" Background="Transparent">
<VisualStateManager.VisualStateGroups >
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background)" Storyboard.TargetName="MyBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="#000000"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</UserControl>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
But its not working.
Below is the sample screenshot
How can i achieve this ?
I would try using the WPToolkit, in which there is the option where you can apply a 'tilt' animation when an item in your ListBox or LongListSelector is pressed. Very cool. First you need to get the toolkit via NuGet in Visual Studio https://www.nuget.org/packages/WPtoolkit/4.2013.8.16 (a link to the site but you add it using the Package Manager Console within Visual Studio itself and it sets everything up automatically). Check this link http://www.davidsalter.com/2013/09/using-windows-phone-toolkit-in-wp8.html and once you have it, Within the tag wher eyou declared the ListBox or LongListSelector itself, insert the following
`<ListBox ... toolkit:TiltEffect.IsTiltEnabled="True" ../>
This should work.

Categories