通过将控件的ViewState与ViewModel的某些属性绑定来更改它的VisualState

时间:2010-10-29 07:14:01

标签: wpf expression-blend viewmodel visualstatemanager

考虑以下代码:

 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>

我试图通过将它绑定到ViewModel中的某个属性来设置Toggle Button的VisualState。 在这里,我无法在“添加引用”列表中找到Microsoft.Expression.Interactivity.dll。我正在使用VS 2010。 我错过了什么?我是否需要安装Expression blend来获取此dll?

另外, 有没有其他方法来完成工作? (通过将控件的某些属性与ViewModel绑定来更改控件的VisualState)。

感谢您的关注。

1 个答案:

答案 0 :(得分:2)

我们使用附加属性来管理元素的自定义状态更改。然后这些只是绑定到视图模型。

e.g。对于“分屏”设置,我们执行以下操作。

在名为SplitScreen的类中创建DependancyProperty,其属性名为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]
    }

当最初设置Attached Property时,你可能会注意到最新更新的小技巧(在页面完全加载之前通常没有父元素)。

在Xaml文件中,将属性附加到所需的元素,如下所示:

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

关键是捕获依赖项属性更改并获取它以更改附加元素的可视状态(这是SplitScreen.cs文件的剪切部分):

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);
}

另一种方法是安装Expression Blend SDK 您不需要Expression Blend来使用SDK和所有很酷的附加功能。对于简单的项目来说,它的工作要少得多(我们只需要一些不支持的自定义行为)。