【问题标题】:Supporting multiple "display modes" menu in a Silverlight Prism application在 Silverlight Prism 应用程序中支持多种“显示模式”菜单
【发布时间】:2011-04-05 11:09:39
【问题描述】:

假设一个标准的桌面资源管理器风格的应用程序:

  • 顶部菜单
  • 左侧导航树
  • 右侧的项目视图

一切都整齐地分为菜单、导航和项目模块。

菜单有一个通用的“视图”->“显示模式”菜单选择,可以改变当前项目视图:

  • “图标视图”
  • “列表视图”
  • “详细视图”

为了捕捉显示类型的变化,我目前发布和订阅了一个 DisplayModeChanged 事件。

第一个问题:

此菜单选项应仅在具有显示模式的适当视图可见时显示。 控制共享菜单按钮以使其仅在至少一个相关视图处于活动状态时才显示的最佳方法是什么?

第二个问题:

如果一个视图在选择之后才存在,它应该如何从菜单中获取当前的显示模式状态?

【问题讨论】:

    标签: silverlight mvvm prism


    【解决方案1】:

    我的第一个想法是,您可以通过将项目视图菜单设置与项目视图一起存储在某处来解决第一个问题。然后,在视图激活时,您将询问您的新视图关于它想要显示的“自定义菜单操作”,其中之一将是项目视图的“显示模式”。其他视图将提供其他菜单操作,并且不会显示此操作。

    但是此解决方案与您的第二个要求相矛盾,因为您显然希望拥有一些全局“ItemViewDisplayModeSetting”,并且每当它发生更改时,您都希望通知所有项目视图并一起更改它们的显示模式。

    所以,让我们通过应用依赖注入原理来解决它。不求事,求事。您的菜单演示者(视图模型)需要一些知道是否存在活动项目视图的服务。您的项目视图演示者需要一项服务,该服务将提供初始显示模式并通知其更改。我们最终得到以下代码:

    interface IActiveViewsService : INotifyPropertyChanged
    {
        bool HasActiveViewsSupportingDisplayMode { get; }
    }
    
    interface IDisplayModeService : INotifyPropertyChanged
    {
        DisplayMode DisplayMode { get; }
    }
    
    //your item view presenter (view model)
    class ItemViewModel
    {
        public ItemViewModel(IDisplayModeService displayModeService)
        {
            //obtain initial setting
            //subscribe to property changes
        }
    }
    
    //your menu presenter (view model)
    class MenuViewModel
    {
        public MenuViewModel(IActiveViewsService activeViewsService)
        {
            //obtain initial setting
            //subscribe to property changes
        }
    }
    

    然后你需要一些方法来从菜单中编辑你的显示模式......你可以将它们组合到 IDisplayModeService 中,或者你可以为此创建一个新界面。该实现将是一个简单的类,它包含一个 DisplayMode 实例,并且您将该类的一个实例注入到您的所有菜单和项目视图中。您还需要实现IActiveViewsService,这可能会从 PRISM 或任何您的 UI 管理机制中包装 IRegionManager ......它将侦听区域更改并在创建新项目视图或没有时做出反应离开了。

    interface IDisplayModeEditor
    {
        void ChangeDisplayMode(DisplayMode newMode);
    }
    
    //your final menu presenter (view model)
    class MenuViewModel
    {
        public MenuViewModel(IActiveViewsService activeViewsService, IDisplayModeEditor modeEditor)
        {
            //obtain initial setting
            //subscribe to property changes
        }
    }
    
    //your final menu presenter (view model)
    class DisplayModeStorage : IDisplayModeService, IDisplayModeEditor
    {
        private DisplayMode displayMode;
    
        public DisplayMode DisplayMode 
        { 
            get { return this.displayMode; } 
    
            //standard propertychange notification
            set
            {
                 if(value == this.displayMode)
                    return;
    
                 this.displayMode = value;
                 this.RaisePropertyChanged("DisplayMode");
            }
        }
    
        public void ChangeDisplayMode(DisplayMode newMode)
        {
             this.DisplayMode = newMode;
        }
    }
    

    HTH。

    【讨论】:

    • 这似乎正是我所需要的。您能否澄清您对实施 IActiveViewsService 的评论?我们目前正在使用来自 PRISM 的 IRegionManager,但我没有在顶层看到任何合适的事件(仅适用于特定区域)。
    • 嗯...好的,代码中必须有一个地方可以创建视图并将它们插入到项目视图区域中...该类可以在区域更改时公开一些事件,例如...也许这不在标准的 PRISM 事件中,你是对的,但是再次从依赖注入的角度考虑它——你需要知道你的区域的人......我记得,在我们的项目中,我们围绕 PRISM 区域管理器做了一个包装器能够使用枚举值而不是字符串作为区域标识符...这样的包装器也可以是您需要的通知器。
    • +50:我试图简化您的答案仍有一些复杂性,但这是一个非常有用的答案,给了我新的想法,做得很好,谢谢:)
    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 2011-05-18
    相关资源
    最近更新 更多