使用MVVM处理Silverlight中的视图状态

时间:2010-02-23 09:50:21

标签: silverlight mvvm

我很想知道那里的人们如何使用MVVM模式处理Silverlight应用程序中的视图状态。 假设我有一个简单的搜索掩码,异步调用Web服务。 搜索正在进行中,我想相应地更改gui: - 禁用“搜索”按钮 - 启用“取消”按钮 - 等等

使用wpf我可以创建一个绑定到viewmodel中某个属性的数据触发器,然后对gui进行更改。 既然我在Silverlight中没有数据触发器,那么与数据触发器类似的最明智的方法是什么(如果可能,在一个地方使用整齐的代码)?

I posted a similar question, but it was worded poorly

4 个答案:

答案 0 :(得分:7)

我这样做的标准方法是从视图模型(通常是枚举)中公开“ViewState”属性。视图然后绑定到属性并使用visualstatemanager根据枚举切换到适当的可视状态。

来自Expression Samples的DataStateSwitchBehavior是关于如何切换到视觉状态的一个很好的例子。

编辑回复评论

首先,当处理VisualStates时使用Blend(不应该强迫任何人手动编写那么多XAML)。我相信它甚至可以用于所有(大多数?)MSDN订阅。

使用Visual States以Visual State Manager

开头
<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="GroupOne">
        <VisualState x:Name="Normal"/>
        <VisualState x:Name="Searching"/>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

您通常会将此添加到layoutroot。

可视状态管理器由一组StateGroups组成,而StateGroups又由一组VisualStates组成。

这些组保持组织的互斥状态,因为您可以在任何时间激活多个视觉状态,但每组只有一个状态。标准模式是使用称为“正常”或“默认”之类的空状态来关闭其他状态。一个基本状态基本上。

在你的情况下,你将有一个“搜索”视觉状态,其中包含一个故事板,可以禁用各种按钮,激活繁忙的动画等。

答案 1 :(得分:0)

最方便的方法是使用 Silverlight Toolkit 中的BusyIndicator。当它掩盖您应用它的整个区域时,所有按钮都会自动禁用。

对于取消按钮,您必须编辑BusyIndicator的模板,将其直接放在我认为的加载动画旁边。

然后,您只需将BusyIndi​​cator的IsBusy属性绑定到ViewModel中您在加载前设置的相应属性,并在完成后重置。

答案 2 :(得分:0)

我的解决方案类似于Graeme Bradbury的,但我不使用DataStateSwitchBehavior,因为如果我的X控件放在一个选项卡面板(或类似的东西)中,当我在另一个选项卡上时状态发生变化,那么我会得到一个例外('找不到元素')。抛出异常是因为我在另一个选项卡上卸载了我的X控件,但找不到需要更新的元素。

所以这就是我的所作所为:

在我的视图模型中,我有一个属性VisualState,它在状态发生变化时发送通知消息(我使用MVVM light toolkit):

private string visualState = XVisualStates.InitialState;
    public string VisualState
    {
        get
        {
            return visualState;
        }

        set
        {
            visualState = value;
            Messenger.Default.Send(new XStateChangedMessage(value));
        }
    }

在我的视图背后的代码中,我订阅了一个通知:

public partial class XControl : UserControl
{
    private string visualState = XVisualStates.InitialState;
    public XControl()
    {
        InitializeComponent();

        //go to state when view is loaded
        Loaded += (s, e) => ChangeState(); //every time a view is loaded go to current state

        //change visual state when a notification is received
        Messenger.Default.Register<XStateChangedMessage>(this,
            state =>
            {
                visualState = state.CurrentState; //save current state
                ChangeState();
            });
    }

    void ChangeState()
    {
        try
        {
            VisualStateManager.GoToState(this, visualState, true); //will throw an exception if current view is unloaded
        }
        catch
        {
            //NOTE: supress 'element' not found errors if user navigated to another view and state changes
        }
    }
}

和XStateChangedMessage是一个简单的类:

public class XStateChangedMessage 
{
    public string CurrentState { get; private set; }

    public XStateChangedMessage (string currentState)
    {
        CurrentState = currentState;
    }
}

答案 3 :(得分:0)

1)您可以在视图模型中创建类似IsEnabledSearch属性的东西,并将其绑定到Button的IsEnabled或Visibility属性(您将需要Bool到Visibility Converter)。仅为此创建新的Visual状态效率不高,因为您的按钮内部已具有所有类型的可视状态以支持此行为。

2)Jounce mvvm框架有一个非常好的实现来支持ViewModel的VisualStates; Jounce Visual State Manager