我很想知道那里的人们如何使用MVVM模式处理Silverlight应用程序中的视图状态。 假设我有一个简单的搜索掩码,异步调用Web服务。 搜索正在进行中,我想相应地更改gui: - 禁用“搜索”按钮 - 启用“取消”按钮 - 等等
使用wpf我可以创建一个绑定到viewmodel中某个属性的数据触发器,然后对gui进行更改。 既然我在Silverlight中没有数据触发器,那么与数据触发器类似的最明智的方法是什么(如果可能,在一个地方使用整齐的代码)?
答案 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
的模板,将其直接放在我认为的加载动画旁边。
然后,您只需将BusyIndicator的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