【问题标题】:Show/Hide views using Visual State Manager silverlight & PRISM使用 Visual State Manager silverlight 和 PRISM 显示/隐藏视图
【发布时间】:2012-09-02 05:58:23
【问题描述】:

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

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

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

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

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

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

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

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

【问题讨论】:

    标签: silverlight prism visualstatemanager


    【解决方案1】:

    可能还有其他访问 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 属性(或者将绑定到此 UserControlDataContext 的任何内容。所以实际上在您使用的 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 有很好的示例。

    这对你有帮助吗?

    【讨论】:

    • 感谢 Jasper,我使用了“DataStateBehavior”,它按预期工作......当然,你需要混合才能工作。
    猜你喜欢
    • 2016-02-22
    • 1970-01-01
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 2019-07-23
    相关资源
    最近更新 更多