【问题标题】:Master page but for Regions?母版页但适用于区域?
【发布时间】:2012-01-04 14:52:18
【问题描述】:

我有一个带有四个按钮的 RibbonBar,每个按钮选择一个不同的视图并将其注入 MainRegion。现在,它运行良好,但四个视图中的每一个都有一些共同的控件,例如显示用户名、日期/时间、搜索框等。到目前为止,我已经制作了单独的视图,但我想知道是否有实现母版页/用户控件的方法,这样我就不必重复代码.

所以现在的设计是这样的:

外壳

<Window>
    <Grid>
        <DockPanel>
            <RibbonBar Regions:RegionManager.RegionName="ToolbarRegion">
            </RibbonBar>
            <ContentControl Regions:RegionManager.RegionName="MainRegion">
            </ContentControl>
        </DockPanel>
    </Grid>
</Window>

ToolbarRegion 包含带有四个按钮的 RibbonBar。

每个 Button 都会将一个视图注入 MainRegion。这些视图中的每一个都有一些通用控件(很像 ASP.Net 中的母版页),但是每个视图的内容是不同的。

有一些方法可以解决这个问题(我无法更改 Shell 设计),但我想知道是否有更好、更优雅的方法来解决这个问题。

【问题讨论】:

  • 当然有这种方式。你尝试了什么?您是否尝试将共享内容移至母版页,并仅在子视图中保留实际内容?
  • 你怎么inject a view into the MainRegion?您使用哪种方法?我有非常密切的应用程序,我可以发布基本结构,但首先我需要知道你现在使用什么:)

标签: wpf mvvm prism


【解决方案1】:

我喜欢使用 Prism 框架,但是我觉得它们的区域应该只用于应用程序布局(MenuRegionNavigationRegionContentRegion 等),而不是导航。将它们用于导航意味着让 View 控制应用程序流程,我觉得这是 ViewModel 的工作。

我首选的显示变化内容的方法是使用 DataTemplates 和 ContentControls

要创建像您概述的那样,我将有一个父 ViewModel,其中包含

  • ObservableCollection&lt;IPageViewModel&gt; PageViewModels
  • IPageViewModel SelectedPageViewModel

我想显示动态内容的区域将使用 ContentControl,例如:

<ContentControl Content="{Binding SelectedPage" />

DataTemplates 将用于告诉 WPF 如何绘制每个部分

<DataTemplate TargetType="{x:Type local:Page1ViewModel}">
    <local:Page1View />
</DataTemplate>

<DataTemplate TargetType="{x:Type local:Page2ViewModel}">
    <local:Page2View />
</DataTemplate>

<DataTemplate TargetType="{x:Type local:Page3ViewModel}">
    <local:Page3View />
</DataTemplate>

我之前没有使用过 RibbonBar,但听起来它应该允许使用 ItemsSource,因此您的最终 XAML 可能看起来类似于以下内容:

<Window>
    <Grid>
        <DockPanel>
            <RibbonBar ItemsSource="{Binding PageViewModels}" 
                       SelectedItem="{Binding SelectedPageViewModel}" 
                       DockPanel.Dock="Top" ...>

            </RibbonBar>

            <StackPanel>
                <Grid>
                    ... Generic Content
                </Grid>

                <ContentControl Content="{Binding SelectedPageViewModel}">

                    <ContentControl.Resources>
                        <DataTemplate TargetType="{x:Type local:Page1ViewModel}">
                            <local:Page1View />
                        </DataTemplate>
                        <DataTemplate TargetType="{x:Type local:Page2ViewModel}">
                            <local:Page2View />
                        </DataTemplate>
                        <DataTemplate TargetType="{x:Type local:Page3ViewModel}">
                            <local:Page3View />
                        </DataTemplate>
                    </ContentControl.Resources>

                </ContentControl>
            </StackPanel>
        </DockPanel>
    </Grid>
</Window>

【讨论】:

  • 有一种简单的方法可以将导航移动到 ViewModel - 使用IRegionManager.RequestNavigate() 方法。在我的应用程序中,我什至将其移至 Service :)
  • @chopikadze 我之前尝试过使用RegionManager,但我真的很讨厌它,因为它引起的混乱,尤其是在子区域和/或更大的应用程序中。我认为它非常适合布置应用程序的不同区域,但除此之外我不使用它。不过这只是我:)
  • 我试过这个并在运行时检查了 SelectedPage 的值。它设置正确。但是,内容控件没有显示与视图模型关联的视图。为了测试方便,我没有对 Ribbonbar 做任何改动,只是简单的对这个方法进行了单视图测试。
  • @DukeCyrillus SelectedPage 是否在值更改时引发 PropertyChange 通知?您的类需要实现INotifyPropertyChanged,并且您需要为 WPF 引发 PropertyChanged 通知以自动更新 UI
  • 我在这里有点困惑... SelectedPage 是视图(即 UserControl)还是视图模型? ContentControl 的内容应该是 UserControl 而不是 ViewModel,对吗?当我在 XAML 中调试并检查 SelectedPage 的值时,它会显示正确的值。我也尝试过引发 Property Changed 事件。它没有用。
【解决方案2】:

Shell.xaml的内容:

<Window ...>
    <StackPanel>
        <Grid>
            <!-- Your shared content -->
        </Grid>
        <ContentControl prism:RegionManager.RegionName="MainRegion"/>
    </StackPanel>
</Window>

【讨论】:

  • 这就是我正在做的,但我没有提到我已经有一个 shell,我拥有的四个视图将分别注入 MainRegion,这意味着我可以在 UserControl 中创建另一个区域(它将被注入 MainRegion),但为了将视图注入这个 SubRegion,我必须在 RibbonBar 控件(位于 Shell 的另一个区域)中引用这些子视图。我会更新我的问题以使其更清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-03
  • 2020-01-07
相关资源
最近更新 更多