我有一个应用程序,使用radOutlookbar在屏幕上显示不同的数据集(用户,国籍等)。 我已经设法在每个项目中加载所需的视图以显示数据没有问题。
然后,我为每个数据集(用户,国籍等)构建了视图,以显示所显示数据集中每个所选项目(即:用户)的详细信息。
案例: 首先,当我点击它的项目时,我需要显示每个数据集的相应视图。 其次,显示的视图将有一个选项来编辑/添加显示的细节。
我想使用状态库导航来实现这种情况。
所以, 我在ItemsControl中有一个PRISM区域,其中有ItemsPanelTemplate网格来托管加载的视图,基本上我加载了每个数据集的视图。
问题, 如何使用VSM根据所选数据集显示/隐藏相应视图?
问题2: 我是否应该能够在加载的视图中定义另一个嵌套状态,以便为每个视图启用编辑/添加详细信息的方案?
如果有人有任何想法这样做,那么获得一个起始代码将会非常有帮助。 最好的问候
答案 0 :(得分:0)
可能有其他方案可以访问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绑定到ViewModelBase中的ViewModelVisualState
属性(或者绑定到DataContext
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的例子。
这对你有帮助吗?