I am developing a Windows Store app, and I hit a problem with scaling to different screen sizes - namely, 140 and 180%. Everything works perfectly on my computer, which is scaled to 100%, but when I test it on the Surface Pro and on the different simulator options that are not scaled to 100%, it starts acting up. I am pretty sure the problem is with the <VisualStateManager> but that is about as far as I can tell.
The problem only appears in the Snapped state, and what happens is in Landscape mode at 140%, the title sometimes appears and sometimes stays blank. Sometimes, clicking the title works to bring up the menu - even if it is blank, while other times nothing happens. The curious part about it is that somehow whether or not it works depends on the data loaded in the DataFrame frame, so if I change the content of those pages to the same content as a working page, it works. The shorter pages appear to have more problems, but that is the only pattern I can find.
When the screen is scaled to 140% portrait mode, none of the text is visible, but some is still clickable.
When the screen is scaled to 180%, the text is not visible, not is it clickable.
Image of title not showing:
Image with title showing:
This is my MainPage.xaml code:
<Page
x:Name="mainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearnOneNote"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="LearnOneNote.MainPage"
mc:Ignorable="d"
Margin="-2">
<Grid Background="White" x:Name="MainGrid">
<Grid.Resources>
<local:StringToTitleConverter x:Key="Convert" />
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="100" x:Name="TitleRow"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" x:Name="ItemsColumn"/>
<ColumnDefinition Width="*" x:Name="DataColumn"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="Items" Grid.Column="0" Grid.RowSpan="2" ItemsSource="{Binding ItemList}" Padding="5" SelectionChanged="newSelect" Tapped="Items_Tapped"/>
<Border x:Name="Border" Grid.Column="1" Margin="10,0,10,10" BorderThickness="0,0,0,2" BorderBrush="Brown" MaxHeight="100" VerticalAlignment="Bottom"/>
<Viewbox x:Name="TitleView" Margin="10,0,10,10" VerticalAlignment="Center" Grid.Column="1" Grid.Row="0">
<TextBlock Foreground="Brown" Text="{Binding ElementName=Items, Path=SelectedValue, ConverterParameter=PrimaryView, Converter={StaticResource Convert}}" Margin="5,10,5,5"/>
</Viewbox>
<Viewbox x:Name="TitleViewSnapped" Margin="10,0,10,10" VerticalAlignment="Center" Grid.Column="1" Grid.Row="0" Visibility="Collapsed">
<TextBlock x:Name="TitleSnapped" Foreground="Brown" Text="{Binding ElementName=Items, Path=SelectedValue, ConverterParameter=Snapped, Converter={StaticResource Convert}}"
Margin="0,10,5,5" PointerEntered="Title_PointerEntered" PointerExited="Title_PointerExited" Tapped="Title_Tapped"/>
</Viewbox>
<Frame Grid.Column="1" Grid.Row="1" Margin="20,20,0,20" x:Name="DataFrame" FontSize="20" Foreground="Black" VerticalAlignment="Top" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ViewStates">
<VisualState x:Name="PrimaryView"/>
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsColumn" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TitleView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TitleViewSnapped" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ItemsSelector">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DataColumn" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsColumn" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="*"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Items" Storyboard.TargetProperty="FontSize">
<DiscreteObjectKeyFrame KeyTime="0" Value="25"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>
If I delete this bit from <VisualState x:Name="Snapped">, I have no problem with my text disappearing, although the clicking problem is still there:
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Title" Storyboard.TargetProperty="Text">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding ElementName=Items, Path=SelectedValue, ConverterParameter=Snapped, Converter={StaticResource Convert}}"/>
</ObjectAnimationUsingKeyFrames>
I searched the internet for other people having this problem and found these MSDN pages:
Scaling to Pixel Density
Resizing to Narrow Layouts
Support Multiple Screen Sizes
I have already made all of these changes to the best of my knowledge.
My simplified program is available in files here
My images are available here
I don't think you can have bindings in animations. I'd try two separate TextBlocks that bind to different values and alternate Visibility of these in visual state storyboards if different text is how you want to differentiate between views.
OK, this is absolutely crazy. I solved my problem by removing the margin of -2 on the page:
<Page
x:Name="mainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearnOneNote"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="LearnOneNote.MainPage"
mc:Ignorable="d"
Margin="-2">
becomes:
<Page
x:Name="mainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LearnOneNote"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="LearnOneNote.MainPage"
mc:Ignorable="d">
Everything started working immediately in all scale sizes, although I have a thin white line around my page. Any information on why this did this and how to remove that white line is welcome.
Related
I suppose, this is a bug.
To reproduce, start the application with dark theme on Windows Phone.
After the application has been launched, change the theme to light.
And after that click "Enable" button.
You will see "Sample" button disappear. because it's theme is still dark.
<Page x:Class="ButtonThemeTest.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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button x:Name="ButtonTest"
Content="Sample"
IsEnabled="False" />
<Button Grid.Row="1"
Click="ButtonBase_OnClick"
Content="Enable" />
<Button Grid.Row="2"
Click="ButtonBase_OnClick2"
Content="Disable" />
</Grid>
</Page>
Code behind:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
ButtonTest.IsEnabled = true;
}
private void ButtonBase_OnClick2(object sender, RoutedEventArgs e)
{
ButtonTest.IsEnabled = false;
}
The only solution I have found is to get Button style from generic.xaml and add a storyboard to Normal visual state like this :
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource PhoneForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource PhoneForegroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource PhoneBackgroundBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
using Visual studio Blend set style to the button.
I'am very new to this WinRT and XAML stuff and not sure how to achieve this goal. For my page layout I have basically 2 rows. The first row is representing my (static) basic menu with some buttons and pictures (about 130 height). The rest of the screen should be used to display content. Like this:
screen layout
now when a user clicks on a main menu button the submenu "filter settings" should be move down with an animation. The main content is also responding to this event and moving accordingly ("filter settings" should not overlay the main content).
My current idea to define this layout is using a grid with 3 rows and 2 frames placed inside it. When no filter is activated, I use rowspan for my main content to span over the whole area. When a click event is recognized, I change the rownum of the frame which hold the main content (ModuleContentFrame) to 2 and its rowspan to 1. Then I'am loading the filter page to frame ModuleFadeInFrame.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="130"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Frame
x:Name="ModuleFadeInFrame"
Grid.Row="1"/>
<Frame
x:Name="ModuleContentFrame"
Grid.Row="1"
Grid.RowSpan="2"/>
</Grid>
My question is: is this layout definition with a grid and frames inside it a suitable solution to solve this problem and how can I achieve a "moving" animation when displaying a sub-menu. I tried this with an Storyboard but there the main content is just "jumping" to row 2
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ModuleContentFrame"
Storyboard.TargetProperty="(Grid.Row)">
<DiscreteObjectKeyFrame KeyTime="1" Value="2" />
</ObjectAnimationUsingKeyFrames>
You can't really animate Grid row/col/etc... changes. Also any animation that'll result in a layout change is a dependent animation - and has bad performance. What I'd do is something like this:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
x:Class="App1.MainPage"
mc:Ignorable="d">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MenuState">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3">
<VisualTransition.GeneratedEasingFunction>
<ExponentialEase EasingMode="EaseInOut"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="ClosedState"/>
<VisualState x:Name="OpenState">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="grid" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid Margin="0,50,0,0" Background="Black">
<TextBlock>
Long text blablabla
</TextBlock>
</Grid>
<Grid x:Name="grid" Margin="0,50,0,0" Height="50" VerticalAlignment="Top" Background="#77ffff00">
<Grid.RenderTransform>
<CompositeTransform TranslateY="-50"/>
</Grid.RenderTransform>
<Button Content="Close" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:GoToStateAction StateName="ClosedState"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
</Grid>
<Grid Margin="0,0,0,0" Height="50" VerticalAlignment="Top" Background="Red">
<Button Content="Open" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:GoToStateAction StateName="OpenState"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
</Grid>
</Grid>
</Grid>
</Page>
This way there's no layout change, as your submenu is going to end up on top of the content.
if you're really insisting on the 'not obscuring content' way
You could just have your submenu before your content with a Height="0", and animate the height of the element with a DoubleAnimation. If you do this, you'll have to set EnableDependentAnimation to true.
More info: https://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.media.animation.pointanimation.enabledependentanimation.aspx
Thank you Tamás, you helped me a lot getting my solution. I'am doing this now as follows:
This code goes into the edit:UserControl for each submenu. On the main page I then only have to handle my Button click events and call the appropriate Animation. Next Step is getting familiar with Blend as you suggested :-)
I marked your post as answer because it was the most helpful in finding my solution
<Grid x:Name="maingrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Grid.RenderTransform>
<CompositeTransform TranslateY="-360"/>
</Grid.RenderTransform>
<Grid.Resources>
<Storyboard x:Name="myStoryboardOpen">
<DoubleAnimation Duration="0:0:0.3" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="maingrid"
d:IsOptimized="True"/>
</Storyboard>
<Storyboard x:Name="myStoryboardClose">
<DoubleAnimation Duration="0:0:0.3" To="-360" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="maingrid"
d:IsOptimized="True"/>
</Storyboard>
</Grid.Resources>
I am making a grid application, and in ItemsDetaiPage.xaml
<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="App6.ItemDetailPage"
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:App6"
xmlns:data="using:App6.Data"
xmlns:common="using:App6.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 items displayed by this page -->
<CollectionViewSource
x:Name="itemsViewSource"
Source="{Binding Items}"
d:Source="{Binding AllGroups[0].Items, 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}"
DataContext="{Binding Group}"
d:DataContext="{Binding AllGroups[0], Source={d:DesignInstance Type=data:SampleDataSource, IsDesignTimeCreatable=True}}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 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" Text="{Binding Title}" Style="{StaticResource PageHeaderTextStyle}" Grid.Column="1"/>
</Grid>
<!--
The remainder of the page is one large FlipView that displays details for
one item at a time, allowing the user to flip through all items in the chosen
group
-->
<FlipView
x:Name="flipView"
AutomationProperties.AutomationId="ItemsFlipView"
AutomationProperties.Name="Item Details"
TabIndex="1"
Grid.Row="1"
Margin="0,-3,0,0"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}">
<FlipView.ItemTemplate>
<DataTemplate>
<!--
UserControl chosen as the templated item because it supports visual state management
Loaded/unloaded events explicitly subscribe to view state updates from the page
-->
<UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates">
<ScrollViewer x:Name="scrollViewer" Style="{StaticResource HorizontalScrollViewerStyle}" Grid.Row="1">
<!-- Content is allowed to flow across as many columns as needed -->
<Grid Margin="120,0,20,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="800"></ColumnDefinition>
<ColumnDefinition Width="40"></ColumnDefinition>
<ColumnDefinition Width="400"></ColumnDefinition>
<ColumnDefinition Width="40"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" Grid.Column="0">
<TextBlock FontSize="26.667" FontWeight="Light" Text="{Binding Title}" TextWrapping="Wrap"/>
<TextBlock FontSize="26.667" FontWeight="Light" Text="{Binding Date}" TextWrapping="Wrap"/>
<WebView x:Name="webView" Width="800" Height="500"/>
<StackPanel x:Name="spButton" Orientation="Horizontal">
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="2">
<TextBlock FontSize="26.667" FontWeight="Light" Text="{Binding Description}" TextWrapping="Wrap"/>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="4">
<TextBlock FontSize="26.667" FontWeight="Light" Text="{Binding Tag}" TextWrapping="Wrap"/>
</StackPanel>
</Grid>
<VisualStateManager.VisualStateGroups>
<!-- Visual states reflect the application's view state inside the FlipView -->
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<!-- Respect the narrower 100-pixel margin convention for portrait -->
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="richTextColumns" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="97,0,87,57"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="image" Storyboard.TargetProperty="MaxHeight">
<DiscreteObjectKeyFrame KeyTime="0" Value="400"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<!-- When snapped, the content is reformatted and scrolls vertically -->
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="richTextColumns" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="17,0,17,57"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="scrollViewer" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource VerticalScrollViewerStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="richTextBlock" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="280"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="image" Storyboard.TargetProperty="MaxHeight">
<DiscreteObjectKeyFrame KeyTime="0" Value="160"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ScrollViewer>
</UserControl>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
<VisualStateManager.VisualStateGroups>
<!-- Visual states reflect the application's view state -->
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<!-- The back button 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>
My apps synthesis clips, each items is a game, each games have views, in StackPanel spButton I want to add buttons as a link to play videos. How can add dynamic buttons in file .cs
This is typical case of invoking controls method through View Model.
To accomplish this, You need to following steps
1. Define an interface INavigatable that expose Navigate event
2. Implement the interface in ViewModel.
3. In the View Code behind, check if DataContext implements INavigatable interface.
4. If step 3 is true, Subscribe to View Model event in view code behind.
Example.
Step 1:
class NavigateEventArgs:EventArgs
{
public string Target {get;set;}
}
public delegate void NavigateEventHandler (object sender, NavigateEventArgs nargs);
public interface INavigatable
{
event NavigateEventHandler Navigate;
}
Step 2:
class MyViewModel : INavigatable
{
public event NavigateEventHandler Navigate;
MyViewModel()
{
NavigateCommand = new DelegateCommand(() =>
{
RaiseNavigateEvent();
}) ;
}
void RaiseNavigateEvent()
{
var temp = Navigate;
if (temp != null)
{
temp(new NavigateEventArgs{Target = Link});
}
}
public string Link {get;set;} // this should be bound to Button.Content (preferably in XAML)
public ICommand NavigateCommand{ get;set;}
}
Step 3/4:
public class MyView : Window
{
public MyView()
{
...
Load += (s,e)=>
{
if (this.DataContext is INavigatable)
{
((INavigatable)(this.DataContext)).Navigate += (s1,e1) => webView.Navigate(e1.Target);
}
}
}
}
As an improvement, subscribe/unsubscribe the Navigate event in DataContextChanged event instead of Load event
I looked on the internet but I can find this nowhere : I would like to disable the TimeHint popup that shows the current time when entering focus on a TimeUpDown control. Something like : <12:42AM>
There is no TimeHintEnabled property, nor any kind of member that seems to control this. There is a TimeHintContent property, but it is readonly and seems empty at first.
My code is really simple :
<Grid x:Name="LayoutRoot" Background="Transparent">
<toolkit:TimeUpDown Name="timeUpDown1"
Background="White"
Height="22"
MinWidth="55"
HorizontalAlignment="Left"
VerticalAlignment="Top" />
</Grid>
Maybe playing with the Template can do the trick, but I don't know how to do it...
Alright, thanks to Blend I found what I was looking for.
The Template can be easily modified by Blend, this part of the template is needed inside the xaml to hide the TimeHintPopup :
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="TimeHintStates">
<VisualState x:Name="TimeHintOpenedUp">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetProperty="Visibility"
Storyboard.TargetName="TimeHintVisualElement">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
And your TimeUpDown should refer to this template :
<toolkit:TimeUpDown Name="timeUpDown1" Background="White" Height="22" MinWidth="55" HorizontalAlignment="Left" VerticalAlignment="Top" Style="{StaticResource TimeUpDownStyle1}" />
Sorry for dummy question, I'm quite new in Silverlight.
I want to dynamically change the layout in my app: for example, I've got two radio buttons: male and female, and I want to show additional controls depending on the gender selected.
For example; If user checks male option, combobox1 should be shown, and if user checks another radio button, another combobox should be shown in the same place.
I can do it with using stackpanel and visible property or with canvas and z property, but I want to know what the best decision is.
And one more question: can one switch through radio buttons, or should use else if statements?
You could do it without code behind.
You could add two states to your control: male and female.
Then you define your two states:
Male state: maleCombobox = Visible, femaleCombobox = Collapsed
Female state: : maleCombobox = Visible, femaleCombobox = Collapsed
Here is the sample xaml (just a quick sample ;) ):
<UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
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:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="SilverlightApplication1.MainPage"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MaleFemaleState">
<VisualState x:Name="FemaleState">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="FemaleCB">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MaleState">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="MaleCB">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<i:Interaction.Triggers>
<ei:PropertyChangedTrigger Binding="{Binding IsChecked, ElementName=MaleRB}">
<ei:GoToStateAction StateName="MaleState"/>
</ei:PropertyChangedTrigger>
<ei:PropertyChangedTrigger Binding="{Binding IsChecked, ElementName=FemaleRB}">
<ei:GoToStateAction StateName="FemaleState"/>
</ei:PropertyChangedTrigger>
</i:Interaction.Triggers>
<StackPanel>
<RadioButton GroupName="1" x:Name="MaleRB" Content="Male"/>
<RadioButton GroupName="1" x:Name="FemaleRB" Content="Female"/>
</StackPanel>
<Grid Margin="40">
<ComboBox x:Name="MaleCB" Visibility="Collapsed">
<ComboBoxItem Content="Male"/>
</ComboBox>
<ComboBox x:Name="FemaleCB" Visibility="Collapsed">
<ComboBoxItem Content="female"/>
</ComboBox>
</Grid>
</Grid>
</UserControl>
Unfortunately for the triggers you need the blend libs. If you don't have blend, you can download a trial or you can define your states and use the VisualStateManager.GoToState in your code behind (http://msdn.microsoft.com/de-de/library/system.windows.visualstatemanager.gotostate(VS.95).aspx). You would listen on the checked event of each radio button and would go to the needed state.
Hope this helps, if you need further explanation just write a comment.
TJ
first of all set GroupName property of the each radio button. Using ChangePropertyAction change visibility of each combobox. e.g.
Visible
Visible