虽然我以前在这种情况下使用过DataTemplateSelector
and IValueConverter
- 现在我最喜欢的方法是使用VisualStateManager
. 我在这里创建了一个最基本的附加属性,它在 WinRT XAML 工具包中实现附加行为模式- 如下所示:
/// <summary>
/// Defines an attached property that controls the visual state of the element based on the value.
/// </summary>
public static class VisualStateExtensions
{
#region State
/// <summary>
/// State Attached Dependency Property
/// </summary>
public static readonly DependencyProperty StateProperty =
DependencyProperty.RegisterAttached(
"State",
typeof(string),
typeof(VisualStateExtensions),
new PropertyMetadata(null, OnStateChanged));
/// <summary>
/// Gets the State property. This dependency property
/// indicates the VisualState that the associated control should be set to.
/// </summary>
public static string GetState(DependencyObject d)
{
return (string)d.GetValue(StateProperty);
}
/// <summary>
/// Sets the State property. This dependency property
/// indicates the VisualState that the associated control should be set to.
/// </summary>
public static void SetState(DependencyObject d, string value)
{
d.SetValue(StateProperty, value);
}
/// <summary>
/// Handles changes to the State property.
/// </summary>
/// <param name="d">
/// The <see cref="DependencyObject"/> on which
/// the property has changed value.
/// </param>
/// <param name="e">
/// Event data that is issued by any event that
/// tracks changes to the effective value of this property.
/// </param>
private static void OnStateChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var stateName = (string)e.NewValue;
var ctrl = (Control)d;
VisualStateManager.GoToState(ctrl, stateName, true);
}
#endregion
}
您应该定义一个枚举样式的类VisualStates
,如 Silverlight Toolkit 中列出所有视觉状态的类(因此您没有重复项),例如
internal static class VisualStates
{
#region GroupCommon
/// <summary>
/// Common state group.
/// </summary>
public const string GroupCommon = "CommonStates";
/// <summary>
/// Normal state of the Common state group.
/// </summary>
public const string StateNormal = "Normal";
/// <summary>
/// Normal state of the Common state group.
/// </summary>
public const string StateReadOnly = "ReadOnly";
/// <summary>
/// MouseOver state of the Common state group.
/// </summary>
public const string StateMouseOver = "MouseOver";
/// <summary>
/// Pressed state of the Common state group.
/// </summary>
public const string StatePressed = "Pressed";
/// <summary>
/// Disabled state of the Common state group.
/// </summary>
public const string StateDisabled = "Disabled";
#endregion GroupCommon
#region GroupFocus
/// <summary>
/// Focus state group.
/// </summary>
public const string GroupFocus = "FocusStates";
/// <summary>
/// Unfocused state of the Focus state group.
/// </summary>
public const string StateUnfocused = "Unfocused";
/// <summary>
/// Focused state of the Focus state group.
/// </summary>
public const string StateFocused = "Focused";
#endregion GroupFocus
}
一旦你有了这些 - 你可以在你的视图模型中拥有一个属性,比如
public string VisualState { get; set; /* Raise PropertyChange event your preferred way here */ }
在你看来说
<Page
...
xmlns:extensions="using:WinRTXamlToolkit.Controls.Extensions"
extensions:VisualStateExtensions.State="{Binding VisualState}">...
然后,您的视图模型可以轻松地驱动视觉状态的变化,您可以使用 Blend 来定义该状态的外观 - 例如,更改布局中各种元素的可见性或简单的可见性Content
。ContentTemplate
我认为这种方法对设计器工具有最好的支持,因为您可以通过单击按钮在视图之间切换并在 Blend 中更新这些视图。