I'm building a windows 8 store app using Visual Studio 2013 express and am coding in Xaml/c#.
When I scroll horizontally or just hold my finger on the screen my animation leaks. By leaks I mean flickering triangles appear randomly outside of the grid performing the animation.
Ive tried various settings in the scrollviewer without any luck. when I remove the scrollviewer the animation performs as expected so it appears the problem lies with the scrollviewer perhaps redrawing the elements on the page.
Below is a test app that shows the problem
MainPage.xaml
<Page.Resources>
<Storyboard x:Name="Storyboard1" AutoReverse="True" RepeatBehavior="Forever">
<DoubleAnimation Duration="0:0:0.8" To="0" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="Border" d:IsOptimized="True"/>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="Border1">
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="-90"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.6" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)" Storyboard.TargetName="Border2">
<EasingDoubleKeyFrame KeyTime="0:0:1.6" Value="-90"/>
<EasingDoubleKeyFrame KeyTime="0:0:2.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="Border3">
<EasingDoubleKeyFrame KeyTime="0:0:2.5" Value="90"/>
<EasingDoubleKeyFrame KeyTime="0:0:3.3" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<ScrollViewer x:Name="MainScroll" ScrollViewer.ZoomMode="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollMode="Disabled">
<StackPanel Orientation="Horizontal">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Width="500" Height="500">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid Grid.RowSpan="2" Grid.ColumnSpan="2" Background="Red"/>
<Border x:Name="Border" Background="Purple" >
<Border.Projection>
<PlaneProjection RotationY="90"/>
</Border.Projection>
</Border>
<Border x:Name="Border1" Background="Purple" Grid.Column="1" >
<Border.Projection>
<PlaneProjection RotationY="-90"/>
</Border.Projection>
</Border>
<Border x:Name="Border3" Background="Purple" Grid.Row="1" >
<Border.Projection>
<PlaneProjection RotationY="90"/>
</Border.Projection>
</Border>
<Border x:Name="Border2" Background="Purple" Grid.Row="1" Grid.Column="1" >
<Border.Projection>
<PlaneProjection RotationX="-90"/>
</Border.Projection>
</Border>
</Grid>
<Grid Width="1000" Background="Blue" Height="300" Margin="50"/>
</StackPanel>
</ScrollViewer>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
Loaded += (s, args) =>
{
this.Storyboard1.Begin();
};
}
}
Thanks in advance
I've seen that before when writing OpenGL code on Android. It turns out I had a bug in my code. OpenGL gives all these nasty bugs when you make mistakes, because it is a giant state machine. Sorry, I can't be of more help. But it sounds like you are doing something wrong somewhere (I was). Could you try commenting things out until the problem no longer occurs? Maybe narrowing it down will help.
Related
I have a button, when user put the mouse over the element I want to show a Popup.
Inside this Popup, contains buttons that user can click.
All of it inside of a Itemscontrol.
I'm already showing the popup when user put the mouse over button, but I don't know how to:
1) Hide popup if the user doesn't "focus" on the popup.
2) If user focus on popup, after focused in button, the popup has to stay opened
My code now:
<Button x:Name="MyButton" MouseEnter="LabelShift_MouseDown" Background="{x:Null}" BorderBrush="{x:Null}" Style="{DynamicResource SquareButtonStyle}" >
<Grid MaxHeight="80">
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Viewbox Grid.Row="0" >
<TextBlock Name="Identifier" FontSize="26" Margin="10,10,10,10" Foreground="White" Text="{Binding Identifier}"/>
</Viewbox>
<Viewbox Grid.Row="1" VerticalAlignment="Bottom">
<TextBlock Name="Value" FontSize="24" Margin="10,10,10,10" Foreground="White" Text="{Binding Total, StringFormat='C'}"/>
</Viewbox>
</Grid>
<Button.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetName="ToolTip"
Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame
KeyTime="00:00:00"
Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetName="ToolTip"
Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame
KeyTime="00:00:00"
Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
<Popup x:Name="ToolTip" PlacementTarget="{Binding ElementName=MyButton}" StaysOpen="True" Placement="Bottom" Height="Auto" Width="{Binding ActualWidth, ElementName=MyButton}" AllowsTransparency="True">
<Grid>
<Border BorderBrush="#909090" BorderThickness="1" CornerRadius="1" >
<StackPanel Margin="10">
<!-- Content/Elements-->
</StackPanel>
</Border>
</Grid>
<Popup.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetName="ToolTip"
Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame
KeyTime="00:00:00"
Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Popup.Triggers>
Here's a simple example of how to achieve drop down functionality. The reason I'm sharing this is because:
a) It inherits the ToggleButton, providing all the functionality we need.
b) Little code.
c) It works!
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
namespace Controls
{
public class DropDownButton : System.Windows.Controls.Primitives.ToggleButton
{
public static readonly DependencyProperty DropDownProperty = DependencyProperty.Register("DropDown", typeof(ContextMenu), typeof(DropDownButton), new UIPropertyMetadata(null));
public ContextMenu DropDown
{
get
{
return (ContextMenu)GetValue(DropDownProperty);
}
set
{
SetValue(DropDownProperty, value);
}
}
public DropDownButton()
{
// Bind the ToogleButton.IsChecked property to the drop-down's IsOpen property
Binding binding = new Binding("DropDown.IsOpen");
binding.Source = this;
this.SetBinding(IsCheckedProperty, binding);
}
protected override void OnClick()
{
if (DropDown != null)
{
//If there is a drop-down assigned to this button, then position and display it
DropDown.PlacementTarget = this;
DropDown.Placement = PlacementMode.Bottom;
DropDown.IsOpen = true;
}
}
}
}
If you wish to use a UserControl in place of the ContextMenu, you can simply add a new property to said control called IsOpen, and, following same logic as above sample, can use bindings to show the UserControl only when the ToggleButton is checked.
In my Universal Windows 10 app, I have an animation that shrinks a custom control whose looks is applied via a template. It works as expected the first time it is run. The second time it is run, the start of the animation is rendered in a horrible resolution, apparently tainted by the previous run:
First time is on the left; second time on the right.
If, instead of using a custom control with a template, I hardcode everything in XAML, the problem doesn't occur.
If I grow rather than shrink the target, the problem doesn't occur.
Let me start with the non-templated version, which is shorter and easier to read than the templated version:
<Page
x:Class="TestApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AnimationStates">
<VisualState x:Name="Show">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleX"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleY"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="Hide" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
FontSize="122"
Text="Q">
<TextBlock.RenderTransform>
<ScaleTransform x:Name="transform" />
</TextBlock.RenderTransform>
</TextBlock>
<Button
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
Content="Animate!"
Click="OnAnimateClicked" />
</Grid>
</Page>
The code-behind is as follows:
public sealed partial class MainPage
{
public MainPage()
{
InitializeComponent();
}
private void OnAnimateClicked(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToState(this, "Hide", useTransitions: false);
VisualStateManager.GoToState(this, "Show", useTransitions: true);
}
}
This works fine every time. But. Instead of applying the ScaleTransform to the TextBlock's RenderTransform directly, I have a custom control with a template applied. For illustration purposes we can use a custom control that is little more than a placeholder:
public sealed class CustomControl : Control
{
}
Then change the XAML to replace the TextBlock with a CustomControl, applying a template to the CustomControl:
<Page
x:Class="TestApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp">
<Grid>
<Grid.Resources>
<Style TargetType="local:CustomControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomControl">
<Grid>
<TextBlock Text="Q" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AnimationStates">
<VisualState x:Name="Show">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleX"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleY"
To="0.1"
BeginTime="0:00:2"
Duration="0:00:1">
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="Hide" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<local:CustomControl
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
FontSize="122">
<local:CustomControl.RenderTransform>
<ScaleTransform x:Name="transform" />
</local:CustomControl.RenderTransform>
</local:CustomControl>
<Button
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="16"
Content="Animate!"
Click="OnAnimateClicked"/>
</Grid>
</Page>
The first time I click the Animate button, this works exactly like the first version. The second and subsequent times, the initial animation rendering uses the really coarse resolution shown on the right:
The coarseness seems to be proportional to the shrinkage factor. Is this a bug of some sort (a failed optimization?), or is my understanding of templates flawed?
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 enjoying the N+1DaysOfMVVMCross but I am stuck on Day 5 (Sort of a day 2 and day 5 combo)...
I used day 2 to develop a grid view UI and wanted to use the day 5 info to add a Command that will open a secondary view when an item is selected from the grid. The Command code in the ViewModel is never executed (though it does execute from a button).
I think the issue is more related to WPF/XAML but thought I would reference MVVMCross as this is where I hit the road block.
Thanks for any help/tips/direction
How about some source code...
From the view model, sorry for the list initialization I'm slowly working through this.
using Cirrious.MvvmCross.ViewModels;
using System.Collections.Generic;
using TeleBacteriology.Core.Services;
namespace TeleBacteriology.Core.ViewModels
{
public class WorklistViewModel : MvxViewModel
{
public WorklistViewModel(IWorklistItemService service)
{
var newList = new List<WorklistItem>();
WorklistItem newWorklistItem = service.CreateNewWorklistItem("201401250001", "http://placekitten.com/301/301");
newList.Add(newWorklistItem);
newWorklistItem = service.CreateNewWorklistItem("201401250002", "http://placekitten.com/302/302");
newList.Add(newWorklistItem);
newWorklistItem = service.CreateNewWorklistItem("201401250003", "http://placekitten.com/303/303");
newList.Add(newWorklistItem);
newWorklistItem = service.CreateNewWorklistItem("201401250004", "http://placekitten.com/304/304");
newList.Add(newWorklistItem);
newWorklistItem = service.CreateNewWorklistItem("201401250005", "http://placekitten.com/305/305");
newList.Add(newWorklistItem);
newWorklistItem = service.CreateNewWorklistItem("201401250006", "http://placekitten.com/306/306");
newList.Add(newWorklistItem);
newWorklistItem = service.CreateNewWorklistItem("201401250007", "http://placekitten.com/307/307");
newList.Add(newWorklistItem);
newWorklistItem = service.CreateNewWorklistItem("201401250008", "http://placekitten.com/308/308");
newList.Add(newWorklistItem);
newWorklistItem = service.CreateNewWorklistItem("201401250009", "http://placekitten.com/309/309");
newList.Add(newWorklistItem);
newWorklistItem = service.CreateNewWorklistItem("201401250010", "http://placekitten.com/310/310");
newList.Add(newWorklistItem);
Worklist = newList;
}
private List<WorklistItem> _worklist;
public List<WorklistItem> Worklist
{
get { return _worklist; }
set { _worklist = value; RaisePropertyChanged(() => Worklist); }
}
private MvxCommand _detailsCommand;
public System.Windows.Input.ICommand DetailsCommand
{
get
{
_detailsCommand = _detailsCommand ?? new MvxCommand(DoDetailsCommand);
return _detailsCommand;
}
}
private void DoDetailsCommand()
{
ShowViewModel<PlateDetailsViewModel>();
}
}
}
The XAML for the view:
<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="TeleBacteriology.Store.Views.WorklistView"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TeleBacteriology.Store.Views"
xmlns:common="using:TeleBacteriology.Store.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 Worklist}"/>
<DataTemplate x:Key="Worklist250x250ItemTemplate">
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding ImageUrl}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding AccessionNum}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="60" Margin="15,0,15,0"/>
<TextBlock Text="{Binding ImageUrl}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</Grid>
</DataTemplate>
<DataTemplate x:Key="Worklist80ItemTemplate">
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="60" Height="60">
<Image Source="{Binding ImageUrl}" Stretch="UniformToFill"/>
</Border>
<StackPanel Grid.Column="1" Margin="10,0,0,0">
<TextBlock Text="{Binding AccessionNum}" Style="{StaticResource ItemTextStyle}" MaxHeight="40"/>
<TextBlock Text="{Binding ImageUrl}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
</StackPanel>
</Grid>
</DataTemplate>
<!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
<x:String x:Key="AppName">My Application</x:String>
</Page.Resources>
<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Horizontal scrolling grid used in most view states -->
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemsGridView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.RowSpan="2"
Padding="116,136,116,46"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
ItemTemplate="{StaticResource Worklist250x250ItemTemplate}"
SelectionMode="None"
IsSwipeEnabled="false"
SelectedItem="{Binding DetailsCommand}"/>
<!-- Vertical scrolling list only used when snapped -->
<ListView
x:Name="itemListView"
AutomationProperties.AutomationId="ItemsListView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.Row="1"
Visibility="Collapsed"
Margin="0,-10,0,0"
Padding="10,0,0,60"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
SelectedItem="{Binding DetailsCommand}"
ItemTemplate="{StaticResource Worklist80ItemTemplate}"
SelectionMode="None"
IsSwipeEnabled="false"/>
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="{StaticResource AppName}" IsHitTestVisible="false" Style="{StaticResource PageHeaderTextStyle}"/>
</Grid>
<Grid Grid.Row="2">
<Button Content="Go Details" Command="{Binding DetailsCommand}" />
</Grid>
<VisualStateManager.VisualStateGroups>
<!-- Visual states reflect the application's view state -->
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" Storyboard.TargetProperty="Padding">
<DiscreteObjectKeyFrame KeyTime="0" Value="96,136,86,56"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<!--
The back button and title have different styles when snapped, and the list representation is substituted
for the grid displayed in all other view states
-->
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="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>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</common:LayoutAwarePage>
I can post for the second view but I don't think that's necessary. Again, if I place a button in the view and set the Command binding to DetailsCommand, the second view pops up just fine. Can't get it to work with item selection on the grid.
From looking at your code, it seems you misunderstood the SelectedItem property of the ListView. It will be populated with one of your WorkListItem objects when the selection changes.
The ListView does not have a command property like the Button does, so you need to handle the SelectionChanged event of the ListView and invoke the Command on your Viewmodel manually.
You can do this in code-behind or take a look at one of the EventToCommand helpers to do it directly in xaml.
I can't come up with a solution for this problem in XAML:
I want to animate the width of the right button to a certain value when IsMouseOver of the left button is true. I dont know where to put this: in a style or template of one of the buttons or in a style on the grid. Is it even possible?
<Border Style="{StaticResource ContentBodyStyle}" x:Name="Border" >
<Grid Width="Auto" Height="Auto" Style="{DynamicResource GridStyle1}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Margin="0,0,0,0" Content="Button" Grid.Row="0" x:Name="BtnLeft" Style="{DynamicResource ButtonStyle1}"/>
<Button Margin="0,0,0,0" Content="Button" Grid.Column="1" x:Name="BtnRight" Width="0"/>
</Grid>
</Border>
Thanks
I am not sure you can set properties for controls outside of the scope of a control with a style assigned to it. Even if it is possible, it doesn't seem right to do so.
What you can do in your scenario is to use event triggers and storyboards, defined anywhere they'd be visible to both buttons. Here's an example of how to modify BtnLeft, although I'd prefer to put the storyboards a bit further up the tree to allow for reuse if necessary:
<Button Margin="0,0,0,0" Content="Button" Grid.Row="0" x:Name="BtnLeft" Style="{DynamicResource ButtonStyle1}">
<Button.Resources>
<Storyboard x:Key="OnMouseEnter1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="BtnRight"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="75"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnMouseLeave1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="BtnRight"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Button.Resources>
<Button.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter" SourceName="BtnLeft">
<BeginStoryboard Storyboard="{StaticResource OnMouseEnter1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave" SourceName="BtnLeft">
<BeginStoryboard Storyboard="{StaticResource OnMouseLeave1}"/>
</EventTrigger>
</Button.Triggers>
</Button>
Instead of the IsMouseOver property, you can use MouseEnter and MouseLeave events. That should give you the same functionality.
Edit: The SourceName property can be omitted from the EventTrigger when that trigger is defined within the scope of the button.