0

我有一个使用 radOutlookbar 在屏幕上显示不同数据集(用户、国籍等)的应用程序。我已经设法在每个项目中加载所需的视图以毫无问题地显示数据。

然后,我为每个数据集(用户、国籍等)构建了视图,以显示所显示数据集中每个选定项目(即:用户)的详细信息。

案例:首先,当我单击它的项目时,我需要显示每个数据集的相应视图。其次,显示的视图将有一个选项来编辑/添加显示的详细信息。

我想使用 state-base-navigation 来实现这个场景。

因此,我在 ItemsControl 中有一个 PRISM 区域,其中 ItemsPanelTemplate 网格来托管加载的视图,基本上我为每个数据集加载视图。

问题,我应该如何使用 VSM 根据所选数据集显示/隐藏相应的视图?

问题 2:我是否应该能够在加载的视图中定义另一个嵌套状态以启用每个视图的编辑/添加详细信息的场景?

如果有人对此有任何想法,那么有一个起始代码将有很大帮助。此致

4

1 回答 1

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 已绑定到ViewModelVisualStateViewModelBase 中的属性(或将绑定到DataContextthis 的任何内容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 有很好的示例。

这对您有帮助吗?

于 2012-09-06T07:07:25.600 回答