开发者

Changing VisualState of a control by binding it with some property of ViewModel

开发者 https://www.devze.com 2023-01-22 06:50 出处:网络
Considering the code below: xmlns:interactivity=\"clr-namespace:Microsoft.Expression.Interactivity;assembly=Microsoft.Expression.Interactivity\"

Considering the code below:

 xmlns:interactivity="clr-namespace:Microsoft.Expression.Interactivity;assembly=Microsoft.Expression.Interactivity"

...

 <ToggleButton IsChecked="{Binding Path=IsGlobalControllerAttached}" Command="{Binding Path=AttachDetachGlobalControllerAction}" ToolTip="{Binding Path=GlobalControllerToolTip}" Visibility="{Binding Path=CanApplyDateFilter, Converter={StaticResource bool2VisibilityConverter}}" Style="{StaticResource toolBarToggleButton}">
                <i:Interaction.Behaviors>
                 开发者_运维技巧   <ei:DataStateBehavior Binding="{Binding IsGlobalControllerCreated}" Value="true" TrueState="Normal" FalseState="Disabled" />
                </i:Interaction.Behaviors>
                <Image Source="../../Common/Images/pin.png"/>
            </ToggleButton>

I am trying to set VisualState of Toggle Button by binding it to some property in ViewModel. Here, I am not able to find the Microsoft.Expression.Interactivity.dll in the "Add Reference" list. I am using VS 2010. What am i missing? Do i need to install Expression blend to get this dll?

Also, Is there any other way to get the job done? ( Changing VisualState of a control by biding it with some property of ViewModel).

Thanks for your interest.


We use Attached Properties to manage custom state changes on elements. These are then just bound to the view model.

e.g. for a "split screen" setting we do the following.

Create a DependancyProperty in a class called SplitScreen, with a property called Mode:

    public class SplitScreen
    {
        public static readonly DependencyProperty ModeProperty =
            DependencyProperty.Register("Mode",
                                        typeof(SplitScreenMode),
                                        typeof(UserControl),
                                        new PropertyMetadata(SplitScreenMode.None,
                                            new PropertyChangedCallback(OnScreenModeChanged)));

        public static void SetMode(DependencyObject obj, SplitScreenMode value)
        {
            obj.SetValue(ModeProperty, value);
        }

        public static SplitScreenMode GetMode(Control obj)
        {
            return (SplitScreenMode)obj.GetValue(ModeProperty);
        }

        static void OnScreenModeChanged(object sender, DependencyPropertyChangedEventArgs args)
        {
            var control = sender as UserControl;
            if (control != null)
            {
                if (control.Parent == null)
                {
                    control.Loaded += (s, e) =>
                                          {
                                              ApplyCurrentState(control);
                                          };
                }
                else
                {
                    ApplyCurrentState(control);
                }
            }
        }
        [snip]
    }

You might note our little trick to late-update the value when Attached Property is initially set (there is often no parent element until the page is fully loaded).

In the Xaml file attach the property to the required element like this:

lib:SplitScreen.Mode="{Binding SplitScreenMode}"

The key is to catch dependency property changes and get that to change the visual state of the attached element (this is the snipped part of the SplitScreen.cs file):

static public void ApplyCurrentState(Control control)
{
    string targetState;
    switch (GetMode(control))
    {
        case SplitScreenMode.Single:
            targetState = SplitScreenModeName.Single;
            break;
        case SplitScreenMode.Dual:
            targetState = SplitScreenModeName.Dual;
            break;
        default:
            targetState = SplitScreenModeName.None;
            break;
    }
    VisualStateManager.GoToState(control, targetState, true);
}

The alternative is to install the Expression Blend SDK You do not need Expression Blend to make use of the SDK and all the cool extras. It is a lot less work for simple items (we just needed some custom behaviour it did not support).

0

精彩评论

暂无评论...
验证码 换一张
取 消