【问题标题】:Handling view state in Silverlight with MVVM使用 MVVM 在 Silverlight 中处理视图状态
【发布时间】:2011-01-20 00:01:34
【问题描述】:

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

使用 wpf,我可以创建一个绑定到视图模型中的某些属性的数据触发器,然后对 gui 进行更改。 现在,由于我在 Silverlight 中没有数据触发器,那么与数据触发器类似的实现这一目标的最明智的方法是什么(简洁的代码,如果可能的话,在一个地方)?

(I posted a similar question, but it was worded poorly)

【问题讨论】:

    标签: silverlight mvvm


    【解决方案1】:

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

    Expression Samples 中的 DataStateSwitchBehavior 是关于如何切换到可视状态的一个很好的示例。

    编辑回应评论

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

    使用视觉状态以Visual State Manager开头

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

    您通常会将其添加到 layoutroot。

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

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

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

    【讨论】:

    • 那么我可以在我的控件(也在子窗口上)定义视觉状态,然后使用 DataStateSwitchBehavior 切换它们吗?例如,一种状态可以是“SearchInProgress”。然后如何使用 VSM 禁用按钮,使其在控件处于“SearchInProgress”时不可点击?
    • 谢谢格雷姆。我让它在一个示例项目中工作,看起来这是要走的路。但是,我似乎遇到了这里提到的同样问题:stackoverflow.com/questions/2118814/…。 VSM 似乎在子窗口中不起作用。现在,我将把所有内容放在 UserControl 中并在子窗口中引用它。我正在使用您提到的 DataStateSwitcher 使其由 ViewModel 驱动。
    【解决方案2】:

    我想最方便的方法是使用 Silverlight Toolkit 中的BusyIndicator。由于它掩盖了您应用它的整个区域,因此所有按钮都会自动禁用。

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

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

    【讨论】:

      【解决方案3】:

      我的解决方案类似于 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;
          }
      }
      

      【讨论】:

        【解决方案4】:

        1) 您可以在视图模型中创建类似于 IsEnabledSearch 的属性,并将其绑定到 Button 的 IsEnabled 或 Visibility 属性(您需要一个 Bool to Visibility Converter)。仅仅为此创建新的视觉状态不是很有效,因为您的按钮内部已经有各种视觉状态来支持这种行为。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多