支持多种“显示模式” Silverlight Prism 应用程序中的菜单

发布于 2024-09-16 14:00:57 字数 464 浏览 3 评论 0 原文

假设有一个标准的桌面资源管理器样式应用程序:

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

,所有内容都整齐地分为菜单、导航和项目模块。

菜单有一个通用的“查看”-> “显示模式”菜单选择,可在以下之间更改当前项目视图:

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

为了捕获显示类型更改,我当前发布并订阅了 DisplayModeChanged 事件。

第一个问题:

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

第二个问题:

如果在进行选择后视图出现,应该如何处理它从菜单中获取当前的显示模式状态?

Assume a standard Desktop Explorer style app:

  • menu at top
  • navigation tree on left
  • item view on right

and everything is neatly separated into Menu, Navigation and Item modules.

The menu has a generic "View" -> "Display mode" menu selection, that changes the current item view between:

  • "Icon view"
  • "List view"
  • "Detail view"

To catch the display type change, I currently publish and subscribe to a DisplayModeChanged event.

First problem:

This menu option should only display when an appropriate view is visible that has the display modes. What is the best way to control shared menu buttons so they only show if at least one relevant view is active?

Second Problem:

If a view comes into existence after the selection was made, how should it pickup the current display mode state from the menu?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

乞讨 2024-09-23 14:00:57

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

但是这个解决方案与您的第二个要求相矛盾,因为您显然希望有一些全局的“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 的 IRegionManager 或您的 UI 管理机制...它将侦听区域更改并在创建新项目视图时做出反应,或者当没有人留下的时候。

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。

My first thought was that you could have solved the first problem by storing item view menu settings somewhere together with your item view. Then, on view activation you would ask your new view about its "custom menu actions" that it wants to show and one of them would be "Display mode" for item view. Other views would provide other menu actions and this one will not be shown.

But this solution contradicts with your second requirement, because you obviously want to have some global 'ItemViewDisplayModeSetting', and whenever it is changed you want all item views to be notified and change their display mode together.

So, let's just solve it right by applying the dependency injection principle. Do not look for things, ask for things. Your menu presenter (view model) requires some service that knows whether there are active item views or not. Your item view presenter requires a service that will provide initial display mode and will notify about its changes. We end up with this code:

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
    }
}

Then you need some way to edit your Diplay Mode from menu... you may combine that together into IDisplayModeService or you may create a new interface for that. The implementation will be a simple class that holds one DisplayMode instance and you inject one instance of that class into all your menus and item views. You'll also need to implement IActiveViewsService, this one will probably wrap IRegionManager from PRISM or whatever is your UI management mechanism... it will listen for region changes and react when a new item view is created or when there is no one left.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文