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
Related
I have a user control like this:
<UserControl>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<HyperlinkButton Grid.Row="0" />
<TextBlock Name="textblock" Grid.Row="1"
Text="{Binding dailyText, ElementName=userControl}">
</TextBlock>
</Grid>
</UserControl>
Nevertheless, I don't know, how can I set a style from mainwindow to user control? I have solved the problem to access to other properties like this:
public static readonly DependencyProperty MyContentProperty =
DependencyProperty.Register("MyContent", typeof(object), typeof(Day), null);
public object MyContent
{
get { return (object)GetValue(MyContentProperty ); }
set { SetValue(MyContentProperty , value); }
}
And then
<local:Day MyContent="Hello World" />
However, it doesn't work the style. There is no change in the sytle.
Thank you.
(Modification)
Below is a mainWindow part.
<Page.Resources>
<Style TargetType="TextBlock" x:Name="MyTextBlockStyle">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="SelectionHighlightColor" Value="Red"/>
<Setter Property="FontSize" Value="10"/>
</Style>
</Page.Resources>
<local:Day MyStyle="{StaticResource MyTextBlockStyle}">
Behind-code part in userControl
public static readonly DependencyProperty MyStyleProperty =
DependencyProperty.Register("MyStyle", typeof(Style), typeof(Day), null);
public Style MyStyle
{
get { return (Style)GetValue(MyStyleProperty); }
set { SetValue(MyStyleProperty, value); }
}
You can use PropertyMetadata to initialise and set Style to your TextBlock. Like,
public Style MyStyle
{
get { return (Style)GetValue(MyStyleProperty); }
set { SetValue(MyStyleProperty, value); }
}
public static readonly DependencyProperty MyStyleProperty =
DependencyProperty.Register("MyStyle", typeof(Style), typeof(Day),
new PropertyMetadata(null, OnStyleChange));
private static void OnStyleChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as Day;
control.textblock.Style = (Style)e.NewValue
}
I want to show a collection of images with entry animations (opacity, translation and rescaling) in a UWP app.
How do I apply unique storyboards to each of these images within the ItemsControl.ItemTemplate DataTemplate so that each image has unique translations and sizes? While the animations are the same, their parameters do change from image to image.
Have been looking for several days on something that works reliably, and all I have found so far is stuff that will not work in UWP apps.
How do I apply unique storyboards to each of these images
Firstly, since you want each of these images has a different animation, I suggest to have a property for the image instance to indicate which animation the image will play.
Then secondly, we need to resolve the issue that with different property value to trigger different Storyboard. For this we could consider to use DataTriggerBehavior of XamlBehaviors package. Install the XamlBehaviors Nuget package through this link.
At last binding the corresponding Storyboard to the trigger it will work.
The following is a completed working demo you could have a test.
XAML
...
xmlns:Interactions="using:Microsoft.Xaml.Interactions.Core"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:Media="using:Microsoft.Xaml.Interactions.Media"
...
<ItemsControl x:Name="itemcontrol">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.Resources>
<Storyboard x:Name="StoryBoardOpacity">
<DoubleAnimation
Storyboard.TargetName="img"
Storyboard.TargetProperty="Opacity"
From="0.0"
To="1.0"
Duration="0:0:5" />
</Storyboard>
<Storyboard x:Name="StoryboardScale">
<DoubleAnimation
Storyboard.TargetName="transform"
Storyboard.TargetProperty="ScaleX"
From="1.0"
To="2.0"
Duration="0:0:5" />
</Storyboard>
</Grid.Resources>
<Image
x:Name="img"
Width="100"
Height="100"
Source="{Binding imageurl}">
<Interactivity:Interaction.Behaviors>
<Interactions:DataTriggerBehavior
Binding="{Binding storyboard}"
ComparisonCondition="Equal"
Value="Opacity">
<Media:ControlStoryboardAction Storyboard="{StaticResource StoryBoardOpacity}" />
</Interactions:DataTriggerBehavior>
<Interactions:DataTriggerBehavior
Binding="{Binding storyboard}"
ComparisonCondition="Equal"
Value="Scale">
<Media:ControlStoryboardAction Storyboard="{StaticResource StoryboardScale}" />
</Interactions:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<Image.RenderTransform>
<CompositeTransform x:Name="transform" />
</Image.RenderTransform>
</Image>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Code behind
private ObservableCollection<OneImage> imageSources;
public MainPage()
{
this.InitializeComponent();
imageSources = new ObservableCollection<OneImage>()
{
new OneImage()
{
imageurl="ms-appx:///Assets/caffe1.jpg",
storyboard="Opacity"
},
new OneImage()
{
imageurl="ms-appx:///Assets/caffe2.jpg",
storyboard="Opacity"
},
new OneImage()
{
imageurl="ms-appx:///Assets/caffe3.jpg",
storyboard="Scale"
}
};
itemcontrol.ItemsSource = imageSources;
}
public class OneImage
{
public string imageurl { get; set; }
public string storyboard { get; set; }
}
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.
I am trying to make a typical Radio Button Style for Windows 10 SplitView Control - With an Icon and text. I tried TemplateBinding the UriSource property to RadioButton's Tag property. But the problem here is that Tag is a string type and UriSource is Uri. So it is not working. Is there a way to Set the UriSource in some other way?
Relevant Snippet of the Style:
<Grid Name="BackgroundGrid" Background="Transparent" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<BitmapIcon Height="38" UriSource="{TemplateBinding Tag}" Margin="5,8,5,5" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" Grid.Column="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" TextWrapping="Wrap" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
And the RadioButton:
<RadioButton Style="{StaticResource SplitViewRadioButtonStyle}" Content="Home" x:Name="Home" Tag="/Assets/Home.png"/>
How about an attached property?
I like this approach over converters 'cause you can attach it to any control you want and it has better performance.
Attached Property
public class Properties
{
public static Uri GetIconUri(DependencyObject obj)
{
return (Uri)obj.GetValue(IconUriProperty);
}
public static void SetIconUri(DependencyObject obj, Uri value)
{
obj.SetValue(IconUriProperty, value);
}
public static readonly DependencyProperty IconUriProperty =
DependencyProperty.RegisterAttached("IconUri", typeof(Uri), typeof(Properties), new PropertyMetadata(null));
}
Binding inside Style
<BitmapIcon UriSource="{Binding Path=(local:Properties.IconUri), RelativeSource={RelativeSource TemplatedParent}}" ...
Usage
<RadioButton local:Properties.IconUri="Assets/Home.png" ...
Simplest way would be to add ms-appx/// as appears to a resource in the app
Tag="ms-appx///Assets/Home.png"
So I worked up a solution by extending the RadioButton Control and Adding two properties i.e., IconUri and IconBitmap.
public static readonly DependencyProperty IconUriProperty = DependencyProperty.Register("IconUri", typeof(Uri), typeof(CustomRadioButton), new PropertyMetadata(null, OnIconBitmapChanged));
private static void OnIconBitmapChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ImageRadioButton current = d as CustomRadioButton;
if(current!=null)
{
current.IconBitmap = new BitmapImage(current.IconUri);
}
}
public Uri IconUri
{
get { return (Uri)GetValue(IconUriProperty); }
set { SetValue(IconUriProperty, value); }
}
public static readonly DependencyProperty IconBitmapProperty = DependencyProperty.Register("IconBitmap", typeof(BitmapImage), typeof(CustomRadioButton), new PropertyMetadata(null));
public BitmapImage IconBitmap
{
get { return (BitmapImage)GetValue(IconBitmapProperty); }
set { SetValue(IconBitmapProperty, value); }
}
And then Binding the Image Control in the Style to IconBitmap. Since, here we are binding to the BitmapImage directly, it doesn't fail. Also works with Web URIs.
Xaml for RadioButton:
<templatedControls:CustomRadioButton IconUri="uri" Style="{StaticResource CustomRadioButtonStyle}"/>
And in its style:
<Image Source="{TemplateBinding IconBitmap}" />
To make the style work with your Extended Radio Button just replace 'Target' of the style from RadioButton to templatedControls:CustomRadioButton, where templatedControls is the XAML namespace which has the CustomRadioButton.
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 !!!