WPF/Silverlight States - Activate from XAML? - wpf

Kind of a quick question:
Is it possible to activate a viewstate from XAML? I have been only able to activate one from CS, using the VisualStateManager.GotoState() method. This would fix some of my MVVM issues if it were easily possible.
Thanks

If you are familiar with Blend behaviors, triggers, and actions there is a GoToStateAction which is a part of the Microsoft.Expression.Interactivity.Core namespace. You will have to reference the interactivity assemblies which are part of the Blend SDK.
Once you have the references set up it's as easy as specifying the GoToStateAction to react to some sort of trigger... all in XAML. Here is an example which fires the action off of the Loaded event using an EventTrigger:
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions">
<Grid x:Name="LayoutRoot">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<ic:GoToStateAction StateName="MyVisualState"/>
</i:EventTrigger>
</i:Interaction.Triggers>
...
</Grid>
</UserControl>
More info and tutorial about the specific GoToState action here.
EDIT: This answer is specific to Silverlight, not sure if this is available in WPF.

Related

Disable Triggers in Design Time

Im developing a WPF Application with a TabControl. Inside the TabItems of this TabControl I have implemented EventTriggers which react on a LeftButtonMouseDownEvent to do some stuff. My Problem is that during Design Time of Visual Studio the Event is triggered and it seems to block any further interactions in the Design Window.
Is there a possibility to ignore the trigger, when my Visual Studio is in Design Time. I would prefer to do this in pure XAML. I know that there exists the "mc:Ignorable" tag, but I want it the other way round. If needed i posted a Code Snippet for you.
Thanks for your help!
<TabItem>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<SomeAction/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TabItem>
I don't know how to do it in xaml, but, may be, adding to code SomeAction this, will resolve your problem.
var isInDesignMode = DesignerProperties.GetIsInDesignMode(new DependencyObject());
if(isInDesignMode)
{
// using in VisualStudio or Blend
}
else
{
// using in application
}
Try extending mc:Ignorable with i for your case, i.e. mc:Ignorable="d i":
<UserControl ...
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
...
d:DesignHeight="600"
d:DesignWidth="800"
...
mc:Ignorable="d i">
...
<TabItem>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<SomeAction/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TabItem>
...
</UserControl>

How to connect ICommand and VisualStateManager together

How can I let my controls on the window know that their states should be changed. I have to use ICommand and since controls can have different states (Enable/Disable , Checked/Unchecked ...) have to handle them with VisualStateManager.
This could be a possible scenario:
When Record button is clicked(Checked) the other controls in the window should be uncheckable and once the recording is finished they should be checkable and many other scenarios.
Any help would be really appreciated.
Thanks.
You can achieve it with the help of interaction and interactivity. See if it helps.
Add below references in your XAML
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
You can bind your ICommand and provide a VisualState name that will be applied when Button is clicked
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding YourICommand}" />
<ei:GoToStateAction StateName="YourVisualStateName" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
If you don't have Blend 4, you can install the Blend 4 SDK to get the current behavior assemblies.

Attaching Command to ScrollViewer.ScrollChanged of ListView

The WPF ListView class can be set up to automatically handle scrolling without an external ScrollViewer and it's possible to register an event handler for the control's internal scrollbar by writing XAML like such:
<ListView ScrollViewer.ScrollChanged="ScrollChanged" />
How to attach it to MVVM light Command? I tried the following, but it doesn't work:
<ListView>
<i:Interaction.Triggers>
<i:EventTrigger EventName="ScrollViewer.ScrollChangedEvent">
<cmd:EventToCommand Command="{Binding ScrollCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
Note: ScrollCommand - is a RelayCommand from my viewmodel.
EventTrigger doesn't trigger for routed events. You can use the solution proposed in this article
to create a RoutedEventTrigger class and use it instead of EventTrigger.
I recommend a Behavior for this. If you don't have Blend, you'll need to get the Blend SDK. But once you have that, you can follow this tutorial to extend the behavior of the ScrollViewer.

Using custom XML namespaces to reference external DLLs in Kaxaml

I can get Kaxaml to load external assemblies using CLR-namespaces, that however is a pain because one needs a lot of mappings to target all the different namespaces in an assembly while the custom XmlnsDefinition on the assembly would allow one to get away with just one or a few.
When looking for a solution i obviously found this question but it only seems to cover the use of CLR-namespaces as none of the answers seemed to work for custom namespaces ("Cannot set unknown member ...").
Example:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:is="http://schemas.microsoft.com/expression/2010/interactions">
<!-- ... -->
<Button Content="Test">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<is:ChangePropertyAction PropertyName="IsOpen"
TargetName="popup"
Value="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
This will not work, however if you use CLRs it does:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:is="clr-namespace:Microsoft.Expression.Interactions;assembly=Microsoft.Expression.Interactions"
xmlns:isc="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions">
<!-- ... -->
<Button Content="Test">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<isc:ChangePropertyAction PropertyName="IsOpen"
TargetName="popup"
Value="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
The is namespace is not used here and i had to add a sub-namespace of the interactions assembly.
It would be ideal if the first method could be made to work.
So while typing this question i stumbled upon one way to use the custom namespaces: You have to make Kaxaml load the assembly at least once.
This can be done using some dummy object which references a CLR-namespace within the referenced assembly. If parsed once this loader can be discarded, of course this needs to be done every time Kaxaml is run.
e.g.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:is="http://schemas.microsoft.com/expression/2010/interactions">
<Page.Resources>
<FrameworkElement x:Key="loader"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:is="clr-namespace:Microsoft.Expression.Interactions;assembly=Microsoft.Expression.Interactions" />
</Page.Resources>
Using snippets or the default file this can be made comparatively convenient while still not ideal so if someone knows a good fix please let me know.

Bind a ICommand to a WPF tabcontrol/tabitem using XAML (MVVM)

I have a WPF 3.5 app built using MVVM pattern. I have a tabcontrol and I want to excecute an ICommand on the view model when the user clicks a certain tab (jn my case the "Preview" tab).
How do I hook up my ICommand to the tabitem or tabcontrol using just the XAML? I am using MVVM so I dont want to use events and get filthy, dirty code in the code-behind.
I think Im missing something simple here!
Thanks,P
Please refer this article : hooking up commands to events
Or you can use this approach
You should use InvokeCommandAction, Looks like this:
<TabItem Header="TabItem">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="SomeCommand"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid />
</TabItem>
Be sure to include the xmlns in the top:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
and of course to reference System.Windows.Interactivity (new in WPF4)

Resources