C# 嵌套视图模型的双向绑定
使用Catel 3.9和DevExpress 15.x 我的客户要求我对应用程序进行一些UI更改,但我不确定是否可以轻松完成 架构:C# 嵌套视图模型的双向绑定,c#,xaml,mvvm,devexpress,catel,C#,Xaml,Mvvm,Devexpress,Catel,使用Catel 3.9和DevExpress 15.x 我的客户要求我对应用程序进行一些UI更改,但我不确定是否可以轻松完成 架构: 有一个具有关联视图和ViewModel的主窗口 主窗口包含一个选项卡控件,其中每个选项卡的内容都是一个单独的视图/视图模型。MainWindow ViewModel不拥有任何嵌套的VM;它们由Catel在运行时通过视图自动构造 旧的UI在每个选项卡项上都有按钮,允许客户加载、保存、显示、筛选等。这些按钮的命令/属性直接绑定到该选项卡的ViewModel,工作正
- 有一个具有关联视图和ViewModel的主窗口
- 主窗口包含一个选项卡控件,其中每个选项卡的内容都是一个单独的视图/视图模型。MainWindow ViewModel不拥有任何嵌套的VM;它们由Catel在运行时通过视图自动构造
<dx:DXTabControl x:Name="MainTabControl"
Grid.Row="1"
Margin="10"
BorderThickness="0"
SelectedIndex="{Binding SelectedTabIndex}"
>
<dx:DXTabItem Header="Getting Started" IsEnabled="True">
<views:GetStarted />
</dx:DXTabItem>
<dx:DXTabItem Header="Validate Student Records" Background="Ivory">
<views:StudentValidation />
</dx:DXTabItem>
<dx:DXTabItem Header="Validate Teacher Records" Background="Ivory">
<views:TeacherValidation />
</dx:DXTabItem>
<dx:DXTabItem Header="Validate Admin Records" Background="Ivory">
<views:AdminRecordValidation />
</dx:DXTabItem>
</dx:DXTabControl>
我正在研究的一些可能的解决方案示例:
现在我们显示了StudentValidation选项卡,客户进入应用程序的主菜单。主菜单仍然绑定到MainWindow,并且每个命令都绑定到MainWindowViewModel。服务如何将主菜单绑定到当前选定选项卡的ViewModel,以便StudentValidationViewModel处理这些命令?我可能遗漏了什么。使用一个保存共享数据的单例模型,这样您就可以从任何您喜欢的地方获取实例。服务就是解决方案。创建注入所有视图模型的解决方案。然后,顶级vm可以更新服务,所有vm都可以通过事件响应更新
请记住,虚拟机只代表内存中的实时视图,因此您可以与它们交互。感谢您的所有建议。我试着给每一个都投票,但作为一个“新手”,我不能。当我完成每一项工作时,我意识到我所要做的就是将主菜单项的特定子集绑定到主窗口上当前焦点选项卡的视图/视图模型。这看起来就像更改菜单项的DataContext一样简单 这是主菜单。FileSubMenu是我需要绑定到当前聚焦的ViewModel的子菜单。其他菜单项可由MainWindowViewModel处理 MainWindow.xaml:
<dxb:MainMenuControl Grid.Row="0"
HorizontalAlignment="Left"
HorizontalContentAlignment="Stretch"
VerticalAlignment="Top"
BarItemDisplayMode="ContentAndGlyph"
>
<dxb:BarStaticItem Content="Validator" Glyph="pack://application:,,,/LexValidator;component/Images/lex-logo.png" />
<dxb:BarSubItem x:Name="FileSubMenu" Content="File">
<dxb:BarButtonItem Content="{Binding LoadRecordsText}" Glyph="{dx:DXImage Image=LoadFrom_16x16.png}" Command="{Binding LoadRecordsFile}"/>
<dxb:BarButtonItem Content="Clear Display" Glyph="{dx:DXImageOffice2013 Image=Clear_16x16.png}" Command="{Binding ClearDisplay}"/>
<dxb:BarButtonItem Content="FTE Counts..." Glyph="{dx:DXImage Image=TextBox_16x16.png}" Command="{Binding ShowFTECounts}"/>
<dxb:BarButtonItem Content="Show Pay Grid..." Glyph="{dx:DXImage Image=Financial_16x16.png}" Command="{Binding ShowPayGrid}"/>
<dxb:BarItemLinkSeparator />
<dxb:BarCheckItem Content="Show Ignored Issues" Glyph="{dx:DXImage Image=ClearFilter_16x16.png}" IsChecked="{Binding ShowIgnoredIssues}" IsEnabled="{Binding IsShowIgnoredIssuesEnabled}" />
</dxb:BarSubItem>
<dxb:BarSubItem Content="Exit">
<dxb:BarButtonItem Content="Exit" Glyph="{dx:DXImage Image=Close_16x16.png}" Command="{Binding ExitApplication}"/>
</dxb:BarSubItem>
<dxb:BarSubItem Content="Help">
<dxb:BarButtonItem Content="About..." Glyph="{dx:DXImageGrayscale Image=Index_16x16.png}" Command="{Binding ShowAboutBox}"/>
</dxb:BarSubItem>
</dxb:MainMenuControl>
我意识到这可能不是很“MVVM”,但它工作得很好,“老板”说“继续做其他事情”。如果上面的代码可以完全用XAML处理,我会更高兴——也许是某种资源
同样,如果我遗漏了什么或者有更好的(更多MVVM)解决方案,请让我知道。我想我知道你的想法。有趣的是——让我看看这些方法是否有效,是否仍然适用于MVVM。(即,我们确实不希望ViewModel可以直接访问菜单UI元素进行修改。)谢谢!哦,我正在一个项目中使用这种方法。这真的取决于你的应用程序的架构,但它为我提供了很好的服务。我一直在我的应用程序中使用服务,它们非常有用。但是,虽然它们解决了很多问题,但我不确定它们是否解决了将主窗口视图中的某些内容与所选选项卡的ViewModel绑定的问题。请参见上面的编辑#2。谢谢
private void MainTabControl_SelectionChanged(object sender, TabControlSelectionChangedEventArgs e)
{
// Turn it off and see if it needs to be enabled.
this.FileSubMenu.IsEnabled = false;
var newTabItem = e.NewSelectedItem as DXTabItem;
if (newTabItem != null)
{
var tabView = newTabItem.Content as UserControl;
if (tabView != null)
{
var tabViewModel = tabView.ViewModel;
if (tabViewModel != null)
{
this.FileSubMenu.DataContext = tabViewModel;
this.FileSubMenu.IsEnabled = true;
}
}
}
}