Im working on an application with validation. However, everything was doing great untill i installed this theme : Theme.
Everything is nice and all, but when i get an validation error, i get this exception:
'validationTooltip' name cannot be found in the name scope of 'System.Windows.Controls.ToolTip'.
I can simply remove where this is called. but im also wondering how this looks and might want to add this.
Anyone has an idea how to solve this?
I'll provide anything you guys desire around this question. code, styles etc.
UPDATE
Now that i commented all the code that gave an error. My own validation template isnt show though.
UPDATE2
I fixed that it shows back my own validation template. full code of his validation is below. if i forgot something. just tell me. thanks in advance
CODE
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid" />
<VisualState x:Name="InvalidUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="InvalidFocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="validationTooltip">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>True</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<Border x:Name="ValidationErrorElement" BorderBrush="{StaticResource ValidationErrorElement}" BorderThickness="{TemplateBinding BorderThickness}" Visibility="Collapsed">
<ToolTipService.ToolTip>
<ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}">
<ToolTip.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="validationTooltip">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>true</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToolTip.Triggers>
</ToolTip>
</ToolTipService.ToolTip>
</Border>
Related
I have some challenges with a code as follows.
I need to start this simpliest animation code by means of e.g. ButtonClick event or a method in Code Behind.
Could anyone shed the light on this matter?
Update: The code itself is working perfectly. I need just start it by a button. Not while window loading.
Thanks in advance!
<StackPanel>
<Button x:Name="Button" Content="Start" Click="Button_Click"/>
</StackPanel>
<Image
Name="img"
Width="128"
Height="128">
<Image.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Duration="0:0:2.0">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="D://Speakers//Wave_00.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:.5">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="D://Speakers//Wave_01.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:1">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="D://Speakers//Wave_02.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:1.5">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="D://Speakers//Wave_03.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
</Grid>
try to change
eventtrigger routedevent="loaded"
in
EventTrigger RoutedEvent="Button_Click"
i hope it works
I am trying to style a toggle button and I want the Foreground colour for the selected state and the MouseOver state to be white.
My style is as follows:
<Window.Resources>
<ControlTemplate x:Key="MenuButton" TargetType="{x:Type ToggleButton}">
<Border x:Name="border" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Cursor)" Storyboard.TargetName="MenuItemContainer">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Cursor>Hand</Cursor>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="menuText">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="icon">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderThickness)" Storyboard.TargetName="border">
<EasingThicknessKeyFrame KeyTime="0" Value="4,0,0,0"/>
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush)" Storyboard.TargetName="border">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="#FF19AA8D"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="icon">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="menuText">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="MenuItemContainer" Orientation="Horizontal" Height="46" Margin="14,0,0,0" Background="Transparent" >
<TextBlock x:Name="icon" Grid.Column="0" VerticalAlignment="Center" FontFamily="{StaticResource FontAwesome}" Foreground="#a7b1c2" FontSize="13" Text="" Margin="0,0,6,0"/>
<TextBlock x:Name="menuText" VerticalAlignment="Center" Foreground="#a7b1c2" FontSize="13" Text="{TemplateBinding Property=ContentControl.Content}"/>
</StackPanel>
</Border>
</ControlTemplate>
</Window.Resources>
This is working fine and for MouseOver and Selected states the foreground is set to white. However in Expression Blend Designer I see a warning message which says "To Avoid Unpredictable behaviour, you should not change an object-property in more than one state ..."
Should I just ignore this warning or is there a better way to implement what I am trying to achieve?
Thanks
Yes, you should care about the warning. And in fact the style doesn't behave correctly. Do the following test:
1: set the button to checked -> the text turns to white -> ok
2: move the mouse away -> the text stays in white -> ok
3: move the mouse over the button -> the text stays in white -> ok
4: move the mouse away -> the text turns back to your non-checked default Color -> not ok
In other words you should not modify the same property of the same control from two different visual state groups. Just because the last change wins.
A solution in your case could be this:
<ControlTemplate x:Key="MenuButton" TargetType="{x:Type ToggleButton}">
<Border x:Name="border" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Cursor)" Storyboard.TargetName="MenuItemContainer">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Cursor>Hand</Cursor>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Visibility)" Storyboard.TargetName="menuTextMouseOver">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="iconMouseOver">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="menuText">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="icon">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderThickness)" Storyboard.TargetName="border">
<EasingThicknessKeyFrame KeyTime="0" Value="4,0,0,0"/>
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush)" Storyboard.TargetName="border">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="#FF19AA8D"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="icon">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="menuText">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="MenuItemContainer" Orientation="Horizontal" Height="46" Margin="14,0,0,0" Background="Transparent" >
<TextBlock x:Name="iconMouseOver" Grid.Column="0" VerticalAlignment="Center" Foreground="White" FontSize="13" Text="the icon" Margin="0,0,6,0" Visibility="Collapsed"/>
<TextBlock x:Name="menuTextMouseOver" VerticalAlignment="Center" Foreground="White" FontSize="13" Text="{TemplateBinding Property=ContentControl.Content}" Visibility="Collapsed"/>
<TextBlock x:Name="icon" Grid.Column="0" VerticalAlignment="Center" Foreground="#a7b1c2" FontSize="13" Text="the icon" Margin="0,0,6,0"/>
<TextBlock x:Name="menuText" VerticalAlignment="Center" Foreground="#a7b1c2" FontSize="13" Text="{TemplateBinding Property=ContentControl.Content}"/>
</StackPanel>
</Border>
</ControlTemplate>
I try to change the button foreground color using visual sate manager its does not work at all.
<Button x:Name="Close" HorizontalAlignment="Stretch"
Width="100" Background="#FF4F4F4F"
Height="50" BorderThickness="2" BorderBrush="#FF2F2F2F"
Content="Cancel">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Close"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="#FFFFFFFF" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Close"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="#FFFFFFFF" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Button>
please help me to work this.
Thanks in advance.
It is not working because you were trying to set Color value for a Brush type.
Please create a Brush StaticResource using the color you need. And set the resource in animation.
<SolidColorBrush x:Key="TextBoxErrorThemeBrush" Color="Red" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PART_TextBlock">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxErrorThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
Regards,
Jessie
I'm trying to grasp some Silverlight animation basics by creating a simple (I'd imagine) transition.
Expected behaviour:
I have a simple UserControl representing an input form with (currently) two states - for testing purposes it's really simplified - a few buttons which don't do anything and a background to make the states more distinct.
The idea is to create a "rotating" effect (using ScaleX transformation) when switching states.
The problem:
I could create a separate animation for a transition from each state to each other state (in the current case of 2 states it'd be very simple) but I'm thinking - if there are more states and I want to be able to change from any of them to any other, then such an approach is hardly ideal.
So I wanted to make use of the generic transitions to and from states, and created the XAML as defined below. The issue is that when switching from one state to the other, for the first half of the transition (0:0:0 -> 0:0:0.2) the state I'm transitioning FROM is invisible (white background, no buttons).
Why is that? How should I create this transition?
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
x:Class="TransitionTest.UserControl1"
d:DesignWidth="640" d:DesignHeight="480" Background="White">
<Grid x:Name="grid1" RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<CompositeTransform/>
</Grid.RenderTransform>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
<VisualTransition GeneratedDuration="0" To="VisualState1">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="State1">
<DiscreteObjectKeyFrame KeyTime="0:0:0.2">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="grid1">
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition From="VisualState1" GeneratedDuration="0">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="border">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseIn"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="State1">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.2">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition GeneratedDuration="0" To="VisualState2">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="grid1">
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="State2">
<DiscreteObjectKeyFrame KeyTime="0:0:0.2">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition From="VisualState2" GeneratedDuration="0">
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="grid1" d:IsOptimized="True">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseIn"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="State2">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.2">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="VisualState1">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="State1">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="VisualState2">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="State2">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<VisualStateManager.CustomVisualStateManager>
<ei:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<Border x:Name="border" BorderBrush="Red" BorderThickness="3" CornerRadius="3" Background="White" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<CompositeTransform/>
</Border.RenderTransform>
<Grid x:Name="grid">
<Grid.RenderTransform>
<CompositeTransform/>
</Grid.RenderTransform>
<Grid x:Name="State1" Margin="0" Background="#FF6CB5E8" Visibility="Collapsed">
<Button Content="Button" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" Width="200"/>
</Grid>
<Grid x:Name="State2" Margin="0" Visibility="Collapsed" Background="#FF80DE5C">
<Button Content="Button" Margin="2,0,3,203" VerticalAlignment="Center" Width="70" HorizontalAlignment="Center"/>
<Button Content="Button" Margin="0,203,0,0" Width="75" RenderTransformOrigin="0.333,1.273" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Grid>
</Border>
</Grid>
Here's the CS file, if it's in any way important:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace TransitionTest
{
[TemplateVisualState(GroupName = "VisualStateGroup", Name = "VisualState1")]
[TemplateVisualState(GroupName = "VisualStateGroup", Name = "VisualState2")]
public partial class UserControl1 : UserControl
{
public UserControl1()
{
// Required to initialize variables
InitializeComponent();
VisualStateManager.GoToState(this, "VisualState1", false);
}
public bool State
{
get { return (bool)GetValue(StateProperty); }
set { SetValue(StateProperty, value); }
}
// Using a DependencyProperty as the backing store for State. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StateProperty =
DependencyProperty.Register("State", typeof(bool), typeof(UserControl1), new PropertyMetadata(false, State_Changed));
private static void State_Changed(DependencyObject dObject, DependencyPropertyChangedEventArgs e)
{
var control = dObject as UserControl1;
if (control.State)
VisualStateManager.GoToState(control, "VisualState2", true);
else
VisualStateManager.GoToState(control, "VisualState1", true);
}
}
}
I'm trying to plan an mvvm based infrastructure, i decided that the view will be bounded directly to the entities through the vm. (the vm will hold the entity reference, and binding will be o entity.propertyName...)
now i got a problem, when user start editing fields in one view, i wanna lock(make readonly) all other view that bound to the entity being under edit.
so my question is:
what changes do i need to do in my design for having the ability to know who(what view) started editing first, and when he finished.. and how to know about changed that came not from the ui(for not locking anything)
First you'll have to define exactly what it means for user to be "editing" an entity.
What action on the user's part signals they are beginning to edit an entity? Clearly when someone types something in a TextBox bound to a model field they are editing the entity. But what if someone clicks a button in the view that clears a property value in the model or sets it to a predefined value. Is that considered "editing" the entity? What if they change the settings of the view so that it shows fewer options and a ComboBox switches the value in the model to a new value because the old value is no longer listed?
What action on the user's part signals they are done editing an entity? Are they done when the focus leaves the control they are on? When the focus leaves the view? When they click "Ok" or "Save"?
Depending on the answers to these questions, several simple solutions present themselves. I'll explain one simple answer. If it doesn't apply please clarify the answers to the above questions.
Supposing:
Any change made to a model object except a data refresh from the database is considered editing, whether it be done with a button, checkbox, etc
The view that contains the focus is considered to be the one who is making the change
"Editing" ends when the view loses focus or the user saves the data.
Then the following will work:
Add a "Reloading" property either as a static property or somewhere within your model
In your data reloading code, set this property "true" and in a finally block set it "false" again
In your model object (or in a data structure shared between your view models and mapped from the model using a weak dictionary), add a property that contains the view model of the view that is currently editing the entity
In your view, add a PropertyChanged handler to your model object when the view model is attached
In the handler, if: a. The Reloading flag is false, b. No view is currently editing the entity, and c. This view's IsKeyboardFocusWithin is true, then record the fact that this view is currently editing the entity
In every view model, attach a handler to the "CurrentlyEditorView" property mentioned in step 3 (either directly or through the separate data structure). Whenever this propety changed, if it is non-null and not the current view model, set an inherited "Locked" property causing the view to lock.
In the view, add a LostFocus event handler that checks if the model's current view is this one, and if so clears it.
Also add a handler for the Save command that does the same thing.
It would really depend on your program structure. I have some similar requirements and I did this in my primaryshell view...
<Grid wpfi:VisualStateAssistant.CurrentVisualState="{Binding Path=CurrentVisualState}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="640" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="480" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ActiveFormStateGroup">
<VisualStateGroup.Transitions>
</VisualStateGroup.Transitions>
<VisualState x:Name="Searching">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="SearchHeaderView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="SearchNavigationView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="SearchResultsView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="DoctorsModuleShell">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="DoctorsModuleNavigationView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="DoctorEdit">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="SearchHeaderView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="SearchNavigationView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="SearchResultsView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="DoctorsModuleShell">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="DoctorsModuleNavigationView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="VisualAlertsStateGroup">
<VisualStateGroup.Transitions>
</VisualStateGroup.Transitions>
<VisualState x:Name="DialogShowing">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="rectangle">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="DialogNotShowing">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="rectangle">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="IsWaiting">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="rectangle">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="WaitControl">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="IsNotWaiting">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="rectangle">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="WaitControl">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DialogFormsStateGroup">
<VisualStateGroup.Transitions>
</VisualStateGroup.Transitions>
<VisualState x:Name="ShowContactInfoEdit">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="rectangle">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="ContactInfoDatagridView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="HideContactInfoEdit">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="rectangle">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="ContactInfoDatagridView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ShowDoctorTaxonomyEdit">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="rectangle">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="DoctorsTaxonomyEditView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="HideDoctorTaxonomyEdit">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="rectangle">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="DoctorsTaxonomyEditView">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<DockPanel Grid.Column="0"
Grid.Row="0"
Grid.ColumnSpan="3"
Grid.RowSpan="3">
<!--TOP-->
<Grid ShowGridLines="False"
DockPanel.Dock="Top">
<views:SearchHeaderView x:Name="SearchHeaderView" />
</Grid>
<!--BOTTOM-->
<Grid ShowGridLines="false"
DockPanel.Dock="Bottom">
<views:SearchNavigationView x:Name="SearchNavigationView" />
<views:DoctorsModuleNavigationView x:Name="DoctorsModuleNavigationView"
Visibility="Collapsed" />
</Grid>
<!--FILL-->
<Grid ShowGridLines="False">
<views:SearchResultsView x:Name="SearchResultsView" />
<views:DoctorsModuleShell x:Name="DoctorsModuleShell"
Visibility="Collapsed" />
</Grid>
</DockPanel>
<Rectangle x:Name="rectangle"
RadiusX="2"
RadiusY="2"
Grid.Column="0"
Grid.Row="0"
Grid.ColumnSpan="3"
Grid.RowSpan="3"
Fill="{StaticResource modalFormHitTestRectangleBrush}"
IsHitTestVisible="True"
Visibility="Collapsed" />
<controls:WaitingControl x:Name="WaitControl"
Width="100"
Height="100"
Visibility="Collapsed"
Grid.Column="1"
Grid.Row="1" />
<views:ContactInfoDatagridView x:Name="ContactInfoDatagridView"
Grid.Column="1"
Grid.Row="1"
Visibility="Collapsed" />
<views:DoctorsTaxonomyEditView x:Name="DoctorsTaxonomyEditView"
Grid.Column="1"
Grid.Row="1"
Visibility="Collapsed" />
</Grid>
Basically I databound my visualstatemanager to a property on my primary viewmodel that would trigger various visual states depending on an enum I created. I got the best help for doing that from Karl Shifflets Stuff Application.
An option would be to use an EventAggegator or use the Mediator pattern to alert other view models that a particular entity instance is under edit. Those viewmodels can set a property IsReadonly = true which can be bound in xaml to make the controls readonly.
Just rasie an out of edit event to tell those viewmodels that it is no longer in reaonly mode.
If you are binding directly to the entity it should be implementing INotifyPropertyChanged which your view model can listen to in order to detect the first edit taking place.
HTH