FlipView crashes when touched - windows-8

In Windows Store App
XAML
<Page
x:Class="FunctionTest.BlankPage1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FunctionTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<Storyboard x:Name="FloatingFlipOver">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.GlobalOffsetZ)" Storyboard.TargetName="FloatingRoot">
<EasingDoubleKeyFrame KeyTime="0" Value="-2000"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<QuarticEase/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="FloatingRoot">
<EasingDoubleKeyFrame KeyTime="0" Value="180"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<QuarticEase/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="FloatingRoot">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Grid>
<Grid x:Name="FloatingRoot" Visibility="Collapsed" Width="500" Height="300">
<Grid.Projection>
<PlaneProjection CenterOfRotationX="0.5" CenterOfRotationY="0.5"/>
</Grid.Projection>
<Rectangle x:Name="FloatingBackground" Fill="SkyBlue" />
<FlipView>
<Grid x:Name="FloatingContainer" Width="300" Height="300">
</Grid>
</FlipView>
</Grid>
<Button Content="Test" HorizontalAlignment="Left" Margin="46,36,0,0" VerticalAlignment="Top" Click="Test_Click"/>
</Grid>
</Page>
Code
private void Test_Click(object sender, RoutedEventArgs e)
{
Button msiBtn = new Button();
msiBtn.Content = "addBtn";
msiBtn.Width = 100; msiBtn.Height = 50;
msiBtn.Tapped += msiBtn_Tapped;
FloatingContainer.Children.Add(msiBtn);
FloatingRoot.Opacity = 0;
FloatingRoot.Visibility = Visibility.Visible;
FloatingFlipOver.Begin();
}
void msiBtn_Tapped(object sender, TappedRoutedEventArgs e)
{
FloatingRoot.Visibility = Visibility.Collapsed;
FloatingContainer.Children.Clear();
}
This works when used with a mouse,
but it will collapse when I touch the button which is added in FloatingContainer,
sometimes, even when I touch the FloatingContainer (not the button), it will also crash.
Is it a bug?

I think you meant crash, not collapse, right? Because that is what I am seeing.
There is a known bug associated with ScrollViewers and projections. I am not sure if it was publicly discussed, but one of the workarounds I heard about that works for me in WinRT XAML Toolkit (in FlipAnimation) seems to work in your case too since a FlipView has a ScrollViewer as part of its template. Basically you need to change the ZoomMode of the ScrollViewer to something else and back and then it works without crashing. To fix the code from your snippet I referenced WinRT XAML Toolkit to use VisualTreeHelperExtensions that helps extract the ScrollViewer and changed the ZoomMode back and forth after the animation completes, as below:
using WinRTXamlToolkit.Controls.Extensions;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
namespace App96
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Test_Click(object sender, RoutedEventArgs e)
{
Button msiBtn = new Button();
msiBtn.Content = "addBtn";
msiBtn.Width = 100; msiBtn.Height = 50;
msiBtn.Tapped += msiBtn_Tapped;
FloatingContainer.Children.Add(msiBtn);
FloatingRoot.Opacity = 0;
FloatingRoot.Visibility = Visibility.Visible;
FloatingFlipOver.Begin();
FloatingFlipOver.Completed -= FloatingFlipOver_Completed;
FloatingFlipOver.Completed += FloatingFlipOver_Completed;
}
void FloatingFlipOver_Completed(object sender, object e)
{
foreach (var sv in FloatingRoot.GetDescendantsOfType<ScrollViewer>())
{
sv.ZoomMode = (ZoomMode)(((int)sv.ZoomMode + 1) % 2);
sv.ZoomMode = (ZoomMode)(((int)sv.ZoomMode + 1) % 2);
}
}
void msiBtn_Tapped(object sender, TappedRoutedEventArgs e)
{
FloatingRoot.Visibility = Visibility.Collapsed;
FloatingContainer.Children.Clear();
}
}
}
The relevant bit of VisualTreeHelperExtensions that you can use if you don't want the entire Toolkit:
public static class VisualTreeHelperExtensions
{
public static IEnumerable<T> GetDescendantsOfType<T>(this DependencyObject start) where T : DependencyObject
{
return start.GetDescendants().OfType<T>();
}
public static IEnumerable<DependencyObject> GetDescendants(this DependencyObject start)
{
var queue = new Queue<DependencyObject>();
var count = VisualTreeHelper.GetChildrenCount(start);
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(start, i);
yield return child;
queue.Enqueue(child);
}
while (queue.Count > 0)
{
var parent = queue.Dequeue();
var count2 = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count2; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
yield return child;
queue.Enqueue(child);
}
}
}
}

Related

How to trigger a trigger

My question relates to how to initiate as action based on user mouse input.
I have a wpf window that displays information on an organization. Some organizations are vendors in which case vendor information is displayed in another row of the grid. I use the following trigger to display/hide that row. This works as desired.
<RowDefinition>
<RowDefinition.Style>
<Style
TargetType="RowDefinition">
<Setter Property="Height" Value="0" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsVendor}" Value="True">
<Setter Property="Height" Value="*" />
</DataTrigger>
</Style.Triggers>
</Style>
</RowDefinition.Style>
</RowDefinition>
For an organization which is not a vendor, the user can click on a button that adds vendor information and links that new information to the organization. However, that action does not cause the trigger to fire. Is there a way to do that? Or is there a different approach that would work better?
In your case, I will use a converter and bind the value of Height property.
<RowDefinition>
<RowDefinition.Style>
<Style TargetType="RowDefinition">
<Setter Property="Height" Value="{Binding IsVendor, Converter={StaticResource IsVendorConverter}}" />
</Style>
</RowDefinition.Style>
</RowDefinition>
The converter will receive your boolean value (IsVendor) and returns "0" if IsVendor is false and "*" if IsVendor is true.
public class IsVendorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var isVendor = (bool)value;
if (isVendor)
{
return "*";
}
return "0";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You didn't share your xaml, but here is a sample used with a button (clicking one button changes the height of the other one).
<Window
x:Class="WpfApp1.MainWindow"
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:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Window.Resources>
<local:IsVendorConverter x:Key="IsVendorConverter" />
</Window.Resources>
<StackPanel Orientation="Horizontal">
<Button Width="200" Height="{Binding IsVendor, Converter={StaticResource IsVendorConverter}}" />
<Button Width="200" Height="100" Click="Button_Click"/>
</StackPanel>
</Window>
Code Behind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
private bool _isVendor = false;
public bool IsVendor {
get { return _isVendor; }
set { _isVendor = value; OnPropertyRaised("IsVendor"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyRaised(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
IsVendor = true;
}
}

Xamarin forms IOS Buttons looking distorted

I have the following XAML code below :
<StackLayout
Grid.Row="2"
Orientation="Horizontal"
VerticalOptions="End"
Margin="0,0,0,20"
Spacing="28">
<Button
x:Name="SignInButton"
Visual="Material"
Padding="5"
Margin="10,0,0,0"
Style="{DynamicResource ButtonSecondary}"
HorizontalOptions="FillAndExpand"
Text="Sign In"
Clicked="SignInButton_Clicked"/>
<Button
x:Name="JoinUsButton"
Visual="Material"
Padding="5"
Margin="0,0,10,0"
Style="{DynamicResource ButtonPrimary}"
HorizontalOptions="FillAndExpand"
VerticalOptions="End"
Text="Join Us"
Clicked="JoinUsButton_Clicked"/>
</StackLayout>
The dynamic resources currently stored in the App.xaml file are as follows :
<Style x:Name="ButtonSecondary" x:Key="ButtonSecondary" TargetType="Button" ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="{DynamicResource SecondaryColor}" />
<Setter Property="TextColor"
Value="{DynamicResource PrimaryTextColor}" />
<Setter Property="BorderWidth"
Value="1" />
<Setter Property="BorderColor"
Value="{DynamicResource SecondaryBorderColor}" />
<Setter Property="CornerRadius"
Value="50" />
</Style>
However, when I run the app on iOS the buttons look like the image below.
However, on the android device, the buttons look like the image below :
Cauuse : In iOS , if you want to achieve the effect like the above image which you get in Android , you need to set the CornerRadius as half of its HeightRequest .
Solution
Option 1
If the size of the button is always a fixed value , you just need to set the HeightRequest in the style
<Style x:Name="ButtonSecondary" x:Key="ButtonSecondary" TargetType="Button" ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="{DynamicResource SecondaryColor}" />
<Setter Property="TextColor"
Value="{DynamicResource PrimaryTextColor}" />
<Setter Property="BorderWidth"
Value="1" />
<Setter Property="BorderColor"
Value="{DynamicResource SecondaryBorderColor}" />
<Setter Property="CornerRadius"
Value="25" />
<Setter Property="HeightRequest"
Value="50" /> // double of CornerRadius
</Style>
Option 2 :
If the size of Button will change in runtime , you could use Custom Renderer to set the CornerRadius in iOS platform .
in Forms
create a custom button
public class MyButton:Button
{
}
in iOS
using Foundation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using App6;
using App6.iOS;
using System.ComponentModel;
[assembly:ExportRenderer(typeof(MyButton),typeof(MyButtonRenderer))]
namespace App6.iOS
{
public class MyButtonRenderer:ButtonRenderer
{
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if(e.PropertyName=="Height")
{
var height = Element.Height;
Control.Layer.MasksToBounds = true;
Control.Layer.BorderColor = UIColor.Black.CGColor;
Control.Layer.CornerRadius = (nfloat)(height / 2.0);
Control.Layer.BorderWidth = (nfloat)0.5;
}
}
}
}
in xaml
<local:MyButton
x:Name="SignInButton"
Visual="Material"
Padding="5"
Margin="10,0,0,0"
Style="{DynamicResource ButtonSecondary}"
HorizontalOptions="FillAndExpand"
Text="Sign In"
/>
While I can't see the exact issue you are seeing with the distortion I do see an inconsistency between platforms. This ultimately comes down to how the individual platforms render the CornerRadius property. Android will limit it to what is visibly sensible (basically half the height/width, whichever is smaller) whereas iOS will just do as you ask.
This image shows on the left what I currently see, the middle is my second solution and the right is my first solution.
My possible solutions are:
Attach a Behavior
public class RoundCornerBehavior : Behavior<Button>
{
protected override void OnAttachedTo(Button button)
{
button.SizeChanged += OnSizeChanged;
base.OnAttachedTo(button);
}
protected override void OnDetachingFrom(Button button)
{
button.SizeChanged -= OnSizeChanged;
base.OnDetachingFrom(button);
}
private void OnSizeChanged(object sender, EventArgs e)
{
var button = (Button) sender;
button.CornerRadius = (int)Math.Min(button.Width, button.Height) / 2;
}
public static readonly BindableProperty AttachBehaviorProperty =
BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(RoundCornerBehavior), false, propertyChanged: OnAttachBehaviorChanged);
public static bool GetAttachBehavior(BindableObject view)
{
return (bool)view.GetValue(AttachBehaviorProperty);
}
public static void SetAttachBehavior(BindableObject view, bool value)
{
view.SetValue(AttachBehaviorProperty, value);
}
static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
{
if (!(view is Button button))
{
return;
}
var attachBehavior = (bool)newValue;
if (attachBehavior)
{
button.Behaviors.Add(new RoundCornerBehavior());
}
else
{
var toRemove = button.Behaviors.FirstOrDefault(b => b is RoundCornerBehavior);
if (toRemove != null)
{
button.Behaviors.Remove(toRemove);
}
}
}
}
Then simply attach in your style:
<Setter Property="roundButton:RoundCornerBehavior.AttachBehavior" Value="true" />
I would suggest writing some kind of Behavior to provide the sensible CornerRadius which would essentially take the Width and Height properties of the control and simply set the CornerRadius to half the smallest value. I will see if I can knock something up to provide a concrete example shortly.
The nice result of this approach will allow you to continue to define the controls as you were previously and keep the logic self contained in the attached behavior.
Sub class button
An alternative would be to sub class Button and created your own RoundedButton that could do the same as the Behavior approach. Then
public class RoundedButton : Button
{
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
this.CornerRadius = (int)Math.Min(width, height) / 2;
}
}

Template 10 Zxing.Mobile.Net

I'm get an issue using the Template 10 Hamburger Template and Zxing.mobile.net library
"Template10": "1.1.12",
"ZXing.Net.Mobile": "2.1.46"
if I add the following code to the Mainpage and Viewmodel, the scanner works correctly and binds the value back to the TextBox but if I add the same code to the details page the returned code wont bind.I'm doing anything wrong.
Mainpage.xaml
<Page x:Class="WindowsApp3.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Behaviors="using:Template10.Behaviors"
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:controls="using:Template10.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:WindowsApp3.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:WindowsApp3.ViewModels"
mc:Ignorable="d">
<Page.DataContext>
<vm:MainPageViewModel x:Name="ViewModel" />
</Page.DataContext>
<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AdaptiveVisualStateGroup">
<VisualState x:Name="VisualStateNarrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for narrow view -->
<Setter Target="stateTextBox.Text" Value="Narrow Visual State" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateNormal">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for normal view -->
<Setter Target="stateTextBox.Text" Value="Normal Visual State" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateWide">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for wide view -->
<Setter Target="stateTextBox.Text" Value="Wide Visual State" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<controls:PageHeader x:Name="pageHeader"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignTopWithPanel="True"
Text="Main Page">
<!-- secondary commands -->
<controls:PageHeader.SecondaryCommands>
<AppBarButton Click="{x:Bind ViewModel.GotoSettings}" Label="Settings" />
<AppBarButton Click="{x:Bind ViewModel.GotoPrivacy}" Label="Privacy" />
<AppBarButton Click="{x:Bind ViewModel.GotoAbout}" Label="About" />
</controls:PageHeader.SecondaryCommands>
</controls:PageHeader>
<RelativePanel EntranceNavigationTransitionInfo.IsTargetElement="True"
RelativePanel.AlignBottomWithPanel="True"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="pageHeader">
<controls:Resizer x:Name="parameterResizer" Margin="16,16,16,0">
<TextBox MinWidth="150"
MinHeight="62"
Header="Parameter to pass"
Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap">
<Interactivity:Interaction.Behaviors>
<!-- enable submit on enter key -->
<Behaviors:KeyBehavior Key="Enter">
<Core:CallMethodAction MethodName="GotoDetailsPage" TargetObject="{Binding}" />
</Behaviors:KeyBehavior>
<!-- focus on textbox when page loads -->
<Core:EventTriggerBehavior>
<Behaviors:FocusAction />
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</TextBox>
</controls:Resizer>
<Button x:Name="submitButton"
Click="{x:Bind ViewModel.GotoDetailsPage}"
Content="Submit"
RelativePanel.AlignBottomWith="parameterResizer"
RelativePanel.RightOf="parameterResizer" />
<TextBlock x:Name="stateTextBox"
Margin="16,16,0,0"
RelativePanel.AlignLeftWith="parameterResizer"
RelativePanel.Below="parameterResizer"
Text="Current Visual State" />
<!-- content -->
<!-- content -->
<Button x:Name="loadButton"
HorizontalAlignment="Center"
Width="180"
Height="50"
RelativePanel.Below="stateTextBox"
Click="{x:Bind ViewModel.QRCodeCick}">
<StackPanel Orientation="Horizontal">
<SymbolIcon Width="48"
VerticalAlignment="Center"
Height="48"
Symbol="Camera" />
<TextBlock Margin="12,0,0,0"
VerticalAlignment="Center"
Text="Read QR Code" />
</StackPanel>
</Button>
<TextBox x:Name="QRTextBox"
PlaceholderText="Enter Code"
Text="{x:Bind ViewModel.QRText,Mode=TwoWay}"
RelativePanel.Below="loadButton"
Margin="0,0,0,12"/>
</RelativePanel>
</RelativePanel>
</Page>
MainPage.xaml.cs
using System;
using WindowsApp3.ViewModels;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using System.Collections.ObjectModel;
namespace WindowsApp3.Views
{
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
}
}
}
MagePageViewModel.cs
using Template10.Mvvm;
using System.Collections.Generic;
using System;
using System.Linq;
using System.Threading.Tasks;
using Template10.Services.NavigationService;
using Windows.UI.Xaml.Navigation;
using ZXing.Mobile;
namespace WindowsApp3.ViewModels
{
public class MainPageViewModel : ViewModelBase
{
MobileBarcodeScanner scanner;
public MainPageViewModel()
{
if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
{
Value = "Designtime value";
}
//Create a new instance of our scanner
scanner = new MobileBarcodeScanner();
// this.Dispatcher
// scanner.Dispatcher = this.Dispatcher;
}
string _Value = "Gas";
public string Value { get { return _Value; } set { Set(ref _Value, value); } }
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
{
if (suspensionState.Any())
{
Value = suspensionState[nameof(Value)]?.ToString();
}
await Task.CompletedTask;
}
public override async Task OnNavigatedFromAsync(IDictionary<string, object> suspensionState, bool suspending)
{
if (suspending)
{
suspensionState[nameof(Value)] = Value;
}
await Task.CompletedTask;
}
public override async Task OnNavigatingFromAsync(NavigatingEventArgs args)
{
args.Cancel = false;
await Task.CompletedTask;
}
public void GotoDetailsPage() =>
NavigationService.Navigate(typeof(Views.DetailPage), Value);
public void GotoSettings() =>
NavigationService.Navigate(typeof(Views.SettingsPage), 0);
public void GotoPrivacy() =>
NavigationService.Navigate(typeof(Views.SettingsPage), 1);
public void GotoAbout() =>
NavigationService.Navigate(typeof(Views.SettingsPage), 2);
public async void QRCodeCick()
{
scanner.UseCustomOverlay = false;
scanner.TopText = "Hold camera up to barcode";
scanner.BottomText = "Camera will automatically scan barcode\r\n\r\nPress the 'Back' button to Cancel";
//Start scanning
var result = await scanner.Scan();
if (result != null)
_QRText = result.Text;
}
string _QRText;
public string QRText { get { return _QRText; } set { Set(ref _QRText, value); } }
}
}
Details.xaml
<Page x:Class="WindowsApp3.Views.DetailPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Behaviors="using:Template10.Behaviors"
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:controls="using:Template10.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:WindowsApp3.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:WindowsApp3.ViewModels"
x:Name="ThisPage"
mc:Ignorable="d">
<Page.DataContext>
<vm:DetailPageViewModel x:Name="ViewModel" />
</Page.DataContext>
<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AdaptiveVisualStateGroup">
<VisualState x:Name="VisualStateNarrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for narrow view -->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateNormal">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for normal view -->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateWide">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for wide view -->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!-- header -->
<controls:PageHeader x:Name="pageHeader"
Frame="{x:Bind Frame}"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignTopWithPanel="True"
Text="Detail Page" />
<!-- content -->
<ScrollViewer EntranceNavigationTransitionInfo.IsTargetElement="True"
Padding="12,8,0,0"
RelativePanel.AlignBottomWithPanel="True"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="pageHeader"
VerticalScrollBarVisibility="Auto">
<StackPanel>
<TextBlock Style="{StaticResource TitleTextBlockStyle}" Text="You passed:" />
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{x:Bind ViewModel.Value, Mode=OneWay, FallbackValue=DesigntimeValue}" />
<Button x:Name="loadButton"
HorizontalAlignment="Center"
Width="180"
Height="50"
Click="{x:Bind ViewModel.QRCodeCick}">
<StackPanel Orientation="Horizontal">
<SymbolIcon Width="48"
VerticalAlignment="Center"
Height="48"
Symbol="Camera" />
<TextBlock Margin="12,0,0,0"
VerticalAlignment="Center"
Text="Read QR Code" />
</StackPanel>
</Button>
<TextBox x:Name="QRTextBox"
PlaceholderText="Enter Code"
Text="{x:Bind ViewModel.QRText,Mode=TwoWay}"
Margin="0,0,0,12"/>
</StackPanel>
</ScrollViewer>
</RelativePanel>
</Page>
DesignPage.xaml.cs
using WindowsApp3.ViewModels;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Controls;
namespace WindowsApp3.Views
{
public sealed partial class DetailPage : Page
{
public DetailPage()
{
InitializeComponent();
NavigationCacheMode = NavigationCacheMode.Disabled;
}
}
}
DesignViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Template10.Common;
using Template10.Mvvm;
using Template10.Services.NavigationService;
using Windows.UI.Xaml.Navigation;
using ZXing.Mobile;
namespace WindowsApp3.ViewModels
{
public class DetailPageViewModel : ViewModelBase
{
MobileBarcodeScanner scanner;
public DetailPageViewModel()
{
if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
{
Value = "Designtime value";
}
//Create a new instance of our scanner
scanner = new MobileBarcodeScanner();
// this.Dispatcher
// scanner.Dispatcher = this.Dispatcher;
}
private string _Value = "Default";
public string Value { get { return _Value; } set { Set(ref _Value, value); } }
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
{
Value = (suspensionState.ContainsKey(nameof(Value))) ? suspensionState[nameof(Value)]?.ToString() : parameter?.ToString();
await Task.CompletedTask;
}
public override async Task OnNavigatedFromAsync(IDictionary<string, object> suspensionState, bool suspending)
{
if (suspending)
{
suspensionState[nameof(Value)] = Value;
}
await Task.CompletedTask;
}
public override async Task OnNavigatingFromAsync(NavigatingEventArgs args)
{
args.Cancel = false;
await Task.CompletedTask;
}
public async void QRCodeCick()
{
scanner.UseCustomOverlay = false;
scanner.TopText = "Hold camera up to barcode";
scanner.BottomText = "Camera will automatically scan barcode\r\n\r\nPress the 'Back' button to Cancel";
//Start scanning
var result = await scanner.Scan();
if (result != null)
_QRText = result.Text;
}
string _QRText;
public string QRText { get { return _QRText; } set { Set(ref _QRText, value); } }
}
}
I see two issues with your code:
1.) The _QRText = result.Text does not fire the PropertyChange for the binding.
2.) The main difference is in the pages' NavigationCacheMode property. You are using NavigationCacheMode.Enabled on MainPage and NavigationCacheMode.Disabled for DesignPage.
In the background the ZXing do a page navigation then a back navigation, so when it navigate back to the MainPage it uses the cached version so the ViewModel is cached too.
But in the DesignPage the caching is disabled so the back navigation creates a new page and view model instance so the following code is called in the old view model and not in the new one.
//Start scanning
var result = await scanner.Scan();
if (result != null)
_QRText = result.Text;
So you need to set the NavigationCacheMode property of the page to NavigationCacheMode.Required where you start the QR Code scanning.

Windows Phone DoubleAnimation for Border

I need to make some kind of property "EnableBlinking" for Border element which enables DoubleAnimation for Opacity with interval.
<Border CornerRadius="5" Background="Red" EnableBlinking="True" />
I found example with but as far as I understand this is not supported in Windows Phone. And there is VisualStateManager. Can someone give me any example or good tutorial? I don't understand do I need to create Style, or new element.
Thanks
You can go for advaced XAML concept and can use Attached property with user control.
Create User Control
<UserControl
.................
<UserControl.Resources>
<Storyboard x:Name="storyBoard">
<DoubleAnimation Storyboard.TargetName="brd"
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
RepeatBehavior="Forever"
AutoReverse="True"
Duration="0:0:0.1"/>
</Storyboard>
</UserControl.Resources>
<Grid>
<Border x:Name="brd" CornerRadius="5" Background="Red"/>
</Grid>
</UserControl>
public sealed partial class BorderControl : UserControl
{
public BorderControl()
{
this.InitializeComponent();
}
public static bool GetEnableBlinking(DependencyObject obj)
{
return (bool)obj.GetValue(EnableBlinkingProperty);
}
public static void SetEnableBlinking(DependencyObject obj, bool value)
{
obj.SetValue(EnableBlinkingProperty, value);
}
// Using a DependencyProperty as the backing store for EnableBlinking. This enables animation, styling, binding, etc...
public static readonly DependencyProperty EnableBlinkingProperty =
DependencyProperty.RegisterAttached("EnableBlinking", typeof(bool), typeof(MainPage), new PropertyMetadata(0, (s, e) =>
{
(s as BorderControl).storyBoard.Begin();
}));
}
MainPage.xaml
<Grid>
<local:BorderControl EnableBlinking="true" HorizontalAlignment="Center" VerticalAlignment="Center" Height="100" Width="100"/>
</Grid>
Here is Source Code:
https://onedrive.live.com/?id=58D8C7A3527E52FB%21105&cid=58D8C7A3527E52FB

Skip state depending on property in View Model

I'm pretty new to MVVM so i assume this is basics. It's a Windows 8.1 app with MVVM light and a Sqlite DB.
I've got a page that contain 4 States. Each State contain a GridView where you can select an item to set a bound property. On the SelectionChanged I go to the next State.
Here's the GridView's xaml :
<GridView Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Essences}" SelectedItem="{Binding SelectedEssense,Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="EssenceGridView" Opacity="0" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="SelectionChanged">
<Core:GoToStateAction StateName="Diametre"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<GridView.ItemTemplate>
<DataTemplate >
<Grid Width="250" Height="80">
<TextBlock Text="{Binding Trigramme}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
The StoryBoards that change States are just Opacity changing.
Now I want to be able to totaly skip one State, because the user want to be able to use some defaults properties (so he don't have to select the same one all the time)
So, if the default property is set in my ViewModel, I want to able to skip one state.
What is the best approach to achieve this in MVVM ?
Edit : With the help of the link of Depechie, I successfully bind my VisualState to property in my ViewModel. I had to update the code because it was for Windows phone 8 and i'm working with Windows 8.1 !!
Here the updated class :
BindVisualStateBehaviorHandler.cs
class BindVisualStateBehaviorHandler : Behavior<FrameworkElement>
{
//
// Dependency property "StateName" that you can bind in Blend.
// Bind this to the enumeration that controls the visual state.
//
public static DependencyProperty StateNameProperty = DependencyProperty.Register(
"StateName",
typeof(string),
typeof(BindVisualStateBehaviorHandler),
new PropertyMetadata(null, StateNamePropertyChanged));
public string StateName
{
get { return (string)GetValue(StateNameProperty); }
set { SetValue(StateNameProperty, value); }
}
//
// When the StateName property changes, switch to the
// new visual state, and play transition animations.
//
private static void StateNamePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
((BindVisualStateBehaviorHandler)obj).UpdateVisualState(
(string)args.NewValue,
useTransitions: true);
}
//
// When the behavior is first attached, go to the visual state,
// but don't play any animations.
//
protected override void OnAttached()
{
UpdateVisualState(
StateName,
useTransitions: false);
base.OnAttached();
}
private void UpdateVisualState(string visualState, bool useTransitions)
{
if (AssociatedObject != null)
{
if (VisualStateUtilities.FindNearestStatefulControl(base.AssociatedObject as FrameworkElement) != null)
{
VisualStateUtilities.GoToState(
VisualStateUtilities.FindNearestStatefulControl(base.AssociatedObject as FrameworkElement),
visualState,
useTransitions);
}
}
}
}
I had to use my own Behavior cuz it was not présent in Microsoft.Xaml.Interactivity
Behavior.cs
public abstract class Behavior<T> : DependencyObject, IBehavior where T : DependencyObject
{
//http://reflectionit.nl/Blog/2013/windows-8-xaml-tips-creating-blend-behaviors
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public T AssociatedObject { get; set; }
protected virtual void OnAttached()
{
}
protected virtual void OnDetaching()
{
}
public void Attach(Windows.UI.Xaml.DependencyObject associatedObject)
{
this.AssociatedObject = (T)associatedObject;
OnAttached();
}
public void Detach()
{
OnDetaching();
}
DependencyObject IBehavior.AssociatedObject
{
get { return this.AssociatedObject; }
}
}
Then in my View :
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AppStates" >
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="SaisieTige" >
...
<VisualState x:Name="Diametre">
...
</VisualState>
<VisualState x:Name="Hauteur">
...
</VisualState>
<VisualState x:Name="Resume">
...
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Interactivity:Interaction.Behaviors>
<Behavior:BindVisualStateBehaviorHandler x:Name="AppStateBehavior" StateName="{Binding StateHandler.AppState,Mode=TwoWay}"></Behavior:BindVisualStateBehaviorHandler>
<Core:EventTriggerBehavior EventName="Loaded">
<Core:InvokeCommandAction Command="{Binding SelectEssenceOrNotCommand}"></Core:InvokeCommandAction>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
I have to call the RaisePropertyCHange each time i change the State :
StateHandler.SetAppState(AppStates.SaisieTige);
RaisePropertyChanged("StateHandler");
ANd Now it's working, thx a lot guys !!!