【发布时间】:2017-05-03 18:44:33
【问题描述】:
好的,我的 Google-Fu 再次达不到标准,我非常感谢您在这里提供一些指导。
我有一个包含多个页面的 WPF 应用程序,其中一个包含一个 TabControl,其中一个选项卡包含一个网格,其中一个列包含一个 StackPanel,上面只有两个项目:一个标签和一个 TreeView .获得内容后,我无需更新 TreeView。该应用程序使用 MVVMLight(伟大的工具包!)来公开数据,并且所述数据按照应有的方式在 mvvm(可观察)属性中公开。我已经检查过了,一旦我设置 ItemsSource 属性,数据本身就以正确的形式可用,所以我知道这不是缺少数据或数据本身的结构。我查看了网络上与搜索词“wpf treeview dictionary”匹配的所有条目(至少前 4 页),所有文章都接近了,但不要让我到达我需要的地方。我遗漏了一些东西,更糟糕的是,IntelliSense 甚至通过为 xaml 设置提供正确的值来“帮助”。所以我知道我已经很接近了,但是在经历了两天的挫折之后,我认输并寻求帮助。
所以...问题的核心:TreeView 需要显示的数据是SortedDictionary<string, List<ServerEntityNameMsSqlSvr>> 的形式。一个 ServerEntityNameMsSqlSvr 类包含多个属性,其中之一是 FullName。我希望 TreeView 显示的是作为父节点的字典键和 List<ServerEntityNameMsSqlSvr> 中每个项目的全名。你会认为这很简单,不是吗?不适合我,我能得到的最接近的方法是显示字典的键,但要么对孩子不显示任何内容(最好的情况),要么抛出异常以空异常(最坏的情况)停止应用程序。
这是我正在使用的 xaml(最坏情况):
<TreeView Grid.Column="0" ItemsSource="{Binding TableHierarchy}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Value}">
<TextBlock Text="{Binding Path=Key}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="awe:ServerEntityNameMsSqlSvr">
<TextBlock Text="{Binding FullName}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
“TableHierarchy”是暴露数据的MVVM属性,它被声明为SortedDictionary<string, List<ServerEntityNameMsSqlSvr>>。 DataType "awe:ServerEntityNameMsSqlSvr" 是一个简单的类,有一些方法和属性,没什么特别的。一层继承,没有接口。在可用的属性中,我只想公开 FullName,它被声明为 public string FullName => _FullName();是的,它调用了一个重载方法来构建全名,但结果是一个简单的字符串(并且方法调用发生在构建数据时,而不是显示时间,iow,值已经存在,至少调试到 setter说明内容正确。
我研究过的一些解决方案建议将数据类型更改为字典以外的其他内容。在这种情况下,这是不可能的,并且鉴于列表有时相当很大,我不想将其重建为其他内容。这需要与声明的排序字典一起使用。
【问题讨论】:
-
"方法调用发生在数据构建时" --
_FullName()在属性getter被调用时被调用。当然,我不能说 in 方法是什么。如果我是一个赌徒,我怀疑其中可能有一个空引用。无论如何:您的 XAML 对我来说非常适合我使用最小的测试视图模型。你能分享足够的代码来重现这个问题吗?谢谢。 -
哦,我明白你在想什么。 这会在构造时调用
_FullName():public string FullName { get; } = _FullName();。这是只读自动属性的初始化程序。相反,您拥有的是“表达式主体属性”:=>右侧的表达式用于属性获取器。每当任何人获得该属性的值时都会调用它。 -
是的,现在你明白我在做什么了——我正在使用一个抽象的祖先类来定义类的功能,但将实现的细节留给后代(这是正确的)在标准 OOP 编程中)。在撰写本文时,我正在回顾层次结构,看看我是否确实错过了一些东西。我不认为我做到了,但是,你可能是对的。仅仅因为单元测试通过,并不意味着真实世界不能抛出我没想到的东西。我会继续发布这个帖子,让大家知道我发现了什么。
-
我会在该属性上放置一个带有 try/catch 的老式 getter,并在 catch 中设置断点。
-
更进一步 - 重建了填充这些属性的整个小工具,并添加了一个用字符串填充所述属性的方法调用。即使在使用与任何方法调用无关的测试字符串对属性进行硬编码后,仍然会失败。我想我会更进一步,构建一个测试 wpf 程序,去掉所有的垃圾,看看它会把我引向何方。
标签: wpf binding treeview mvvm-light sorteddictionary