【发布时间】:2011-01-06 01:11:44
【问题描述】:
我是 WPF 的新手,尝试构建一个遵循 Josh Smith 描述 The Model-View-ViewModel Design Pattern 的优秀文章的建议的项目。
使用 Josh 的示例代码作为基础,我创建了一个简单的应用程序,其中包含许多“工作区”,每个工作区由 TabControl 中的一个选项卡表示。在我的应用程序中,工作区是一个文档编辑器,它允许通过 TreeView 控件操作分层文档。
虽然我已成功打开多个工作区并在绑定的 TreeView 控件中查看其文档内容,但我发现 TreeView 在选项卡之间切换时会“忘记”其状态。例如,如果Tab1中的TreeView部分展开,切换到Tab2返回Tab1后会显示为完全折叠。此行为似乎适用于所有控件的控件状态的所有方面。
经过一些实验,我意识到我可以通过将每个控件状态属性显式绑定到底层 ViewModel 上的专用属性来保留 TabItem 中的状态。但是,这似乎需要做很多额外的工作,因为我只想让所有控件在工作区之间切换时记住它们的状态。
我假设我遗漏了一些简单的东西,但我不确定在哪里寻找答案。任何指导将不胜感激。
谢谢, 蒂姆
更新:
根据要求,我将尝试发布一些演示此问题的代码。但是,由于 TreeView 基础的数据很复杂,我将发布一个简化的示例,展示相同的症状。这是主窗口中的 XAML:
<TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=Docs}">
<TabControl.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Path=Name}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<view:DocumentView />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
上述 XAML 正确绑定到 DocumentViewModel 的 ObservableCollection,每个成员都通过 DocumentView 呈现。
为简单起见,我从 DocumentView 中删除了 TreeView(上面提到过),并将其替换为包含 3 个固定选项卡的 TabControl:
<TabControl>
<TabItem Header="A" />
<TabItem Header="B" />
<TabItem Header="C" />
</TabControl>
在这种情况下,DocumentView 和 DocumentViewModel 之间没有绑定。代码运行时,切换外层TabControl时,内层TabControl无法记住自己的选择。
但是,如果我显式绑定内部 TabControl 的 SelectedIndex 属性...
<TabControl SelectedIndex="{Binding Path=SelectedDocumentIndex}">
<TabItem Header="A" />
<TabItem Header="B" />
<TabItem Header="C" />
</TabControl>
...到 DocumentViewModel 上的相应虚拟属性...
public int SelecteDocumentIndex { get; set; }
...内部选项卡能够记住它的选择。
我知道我可以通过将这种技术应用于每个控件的每个视觉属性来有效地解决我的问题,但我希望有一个更优雅的解决方案。
【问题讨论】:
-
默认情况下,WPF 中的控件“记住”它们的状态,选项卡项中的控件“忘记”它们的状态这一事实是您的某些显式操作的结果。显示选项卡项的 XAML,以及它们包含的绑定的相关视图模型代码。
-
我同意 Aviad 的观点,如果没有看到您的代码,很难判断出了什么问题。对于 WPF 中 TreeView 控件的一些精彩文章,我建议看看 Bea Stollnitz 的博客...bea.stollnitz.com/blog/index.php?s=treeview
-
我收回我的评论,这是一个真正令人讨厌的问题,我只是从各个角度尝试过,如果选项卡控件使用
ItemsSource和DataTemplate数据模板中控件的状态在选项卡项之间共享 (!!!)! -
我遇到的问题不仅仅是树视图...如果您没有支持控件状态的双向 ViewModel,它将丢失它。这样做的原因是,当您切换选项卡时,控件不再是可视化树的一部分。 Unload 事件实际上是为这些控件触发的,并且在您切换回来之前,它们不再具有任何视觉表示。这是选项卡控件实现的一种虚拟化形式,可在您有很多选项卡时帮助节省内存。很想知道您是否为此提出了解决方案……我刚刚创建了虚拟机。
-
@Killercam:IIRC,2010 年 1 月存在的 WAF 样本对指导我找到可行的解决方案非常有帮助,但随后发生了很大的变化,以至于它试图做很多事情,并且关于这一点已经不是很清楚了。我最近重新访问它以刷新我的记忆(近 3 年没有使用 WPF)并且很失望地发现我无法重现我以前取得的成就。最后,我只是在视图模型上创建了额外的视觉状态属性。抱歉,我无法提出更有帮助的建议。
标签: wpf mvvm binding tabcontrol state