VSM にアクセスするための他のスキームがあるかもしれませんが、私はそのための AttachedProperty を作成することを好みます。説明させてください。
ここに VisualState マネージャーがあります
/// <summary>
/// Class will allow to change VisualSate on ViewModel via attached properties
/// </summary>
public static class VisualStateManagerEx
{
private static PropertyChangedCallback callback = new PropertyChangedCallback(VisualStateChanged);
/// <summary>
/// Gets the state of the visual.
/// </summary>
/// <param name="obj">The obj.</param>
/// <returns></returns>
public static string GetVisualState(DependencyObject obj)
{
return (string)obj.GetValue(VisualStateProperty);
}
/// <summary>
/// Sets the state of the visual.
/// </summary>
/// <param name="obj">The obj.</param>
/// <param name="value">The value.</param>
public static void SetVisualState(DependencyObject obj, string value)
{
obj.SetValue(VisualStateProperty, value);
}
/// <summary>
/// DP for 'VisualState'
/// </summary>
public static readonly DependencyProperty VisualStateProperty =
DependencyProperty.RegisterAttached(
"VisualState",
typeof(string),
typeof(VisualStateManagerEx),
new PropertyMetadata(null, VisualStateManagerEx.callback)
);
/// <summary>
/// Visuals the state changed.
/// </summary>
/// <param name="d">The d.</param>
/// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
public static void VisualStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//Control changeStateControl = d as Control;
FrameworkElement changeStateControl = d as FrameworkElement;
if (changeStateControl == null)
throw (new Exception("VisualState works only on Controls type"));
if (Application.Current.Dispatcher.CheckAccess() == false)
{
// Wrong thread
System.Diagnostics.Debug.WriteLine("[VisualStateManagerEx] 'VisualStateChanged' event received on wrong thread -> re-route via Dispatcher");
Application.Current.Dispatcher.BeginInvoke(
//() => { VisualStateChanged(d, e); }
VisualStateManagerEx.callback
, new object[] { d, e }); //recursive
}
else
{
if (string.IsNullOrEmpty(e.NewValue.ToString()) == false)
{
//VisualStateManager.GoToState(changeStateControl, e.NewValue.ToString(), true);
VisualStateManager.GoToElementState(changeStateControl, e.NewValue.ToString(), true);
System.Diagnostics.Debug.WriteLine("[VisualStateManagerEx] Visual state changed to " + e.NewValue.ToString());
}
}
}
}
今 - XAML では、次のように ViewModel にアタッチします。
<UserControl
xmlns:VSManagerEx=clr-namespace:Namespace.namespace;assembly=Assembly01"
VSManagerEx:VisualStateManagerEx.VisualState="{Binding Path=ViewModelVisualState, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
...
...
これで、XAML の VSM はViewModelVisualState
ViewModelBase のプロパティにバインドされます (またはDataContext
thisにバインドされるものは何でもUserControl
。したがって、実際に使用している ViewModelBase は次のようになります。
/// <summary>
/// Base class for all 'view-models'
/// </summary>
[Export(typeof(ViewModelBase))]
public abstract class ViewModelBase : INavigationAware, INotifyPropertyChanged
{
private SynchronizationContext parentSyncContent;
#region VisualState
private string viewModelVisualState = string.Empty;
/// <summary>
/// Gets or sets the state of the view model visual.
/// </summary>
/// <value>
/// The state of the view model visual.
/// </value>
public virtual string ViewModelVisualState
{
get { return viewModelVisualState; }
set
{
viewModelVisualState = value;
RaisePropertyChanged(this, "ViewModelVisualState");
}
}
#endregion
/// <summary>
/// Raises the property changed.
/// </summary>
/// <param name="Sender">The sender.</param>
/// <param name="PropertyName">Name of the property.</param>
public void RaisePropertyChanged(object Sender, string PropertyName)
{
parentSyncContent.Post((state) =>
{
if (PropertyChanged != null)
PropertyChanged(Sender, new PropertyChangedEventArgs(PropertyName));
}, null);
}
...
...
したがって、この ViewModelBase から継承する任意の ViewModel で、独自の VMS 状態を宣言し、次のように管理できます。
[Export(typeof(IViewModel1))
public ViewModel1 : ViewModelBase, IViewModel1
{
private const string VM_STATE_WORKING = "WorkingState";
internal void StartWorking()
{
this.ViewModelVisualState = VM_STATE_WORKING;
...
...
質問 2 について: いいえ - 何かの中で追加のビューを宣言する必要はありません。ナビゲーションに関する PRISM ドキュメントを参照してください。さまざまなプレゼンテーション ロジックをサポートする View/ViewModel の作成方法に関する優れた例があります。
これは役に立ちましたか?