【问题标题】:The bidirectional binding requires "Path" or "XPath" exception. Windows WPF双向绑定需要“Path”或“XPath”例外。视窗 WPF
【发布时间】:2020-01-30 22:59:58
【问题描述】:

在一个看起来像这样的 Datagrid 中,我遇到了一个异常:

<DataGrid x:Name="ModuleGrid" AutoGenerateColumns="False" CanUserAddRows="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Module Name" Binding="{Binding Path=Name}"/>
        <DataGridTextColumn Header="uName" Binding="{Binding Path=UniqueName}"/>
        <DataGridTemplateColumn Header="Features">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=Feature.Name}"></TextBlock>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <ComboBox ItemsSource="{Binding Path=Features}"
                              SelectedItem="{Binding Path=Feature}">
                        <ComboBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Path=Name}"></TextBlock>
                            </DataTemplate>
                        </ComboBox.ItemTemplate>
                    </ComboBox>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

到目前为止一切顺利,几乎一切正常。但是,当我在我的 ComboBox 上选择 Item 时:

我得到了例外:

System.InvalidOperationException: "Die bidirektionale Bindung erfordert“路径”或“XPath”。”

后面的 C# 代码是一个对象,其中包含一个功能列表 (List&lt;Feature&gt;),其中包含Features。我这样初始化它:

 List<Module> test_3 = pPP_2.Components.Modules.Values.Cast<Module>().ToList();
 ModuleGrid.ItemsSource = test_3;

编辑:模块类:

class Module
    {
        public string Name { get; set; }
        public string UniqueName { get; set; }
        public Dictionary<Property, double> Properties { get; set; }
        public List<Feature> Features { get; set; }

        private Dictionary<Material, double> content = new Dictionary<Material, double>();
        public Dictionary<Material, double> Content
        {
            get { return content; }
            set { content = value; }
        }
        public double FillingCapacity { get; set; }
        public double FillingAmount
        {
            get
            {
                double ret = 0;
                foreach (double a in Content.Values)
                {
                    ret += a;
                }
                return ret;
            }
        }
    }

要素类:

class Feature
    {
        public string Name { get; set; }
        public string FeatureType { get; set; }
        public Property UsedProperty { get; set; }
        public double MinValue { get; set; }
        public double MaxValue { get; set; }
        public double ChangePerMinutePerLiter { get; set; }
    }

属性类:

    class Property
    {
        public string Name { get; set; }
        public double DefaultValue { get; set; }
        public string Unit { get; set; }
    }

【问题讨论】:

  • Module 是自定义类吗?如果是这样,您可以将其添加到您的帖子中吗?另外,StackTrace 中是否有更多关于异常的信息,例如行号等?
  • 添加了所有内容。 StackTrace 中没有关于行等的信息,它只告诉我编译 main() 时失败
  • 感谢您添加。您能否展示一下您是如何创建pPP_2 的?我认为 WPF 在某个级别为该对象的值解析属性可能存在问题。可能是由于其中一个值不是属性,而是普通的旧字段。另外,您是否尝试过将 test_3 声明为具有 getter 和 setter 的属性?
  • 您的意思是Components 是一个存在于名为pPP_2 的文件夹中的类,并且该文件夹中项目的命名空间是WPFProjectName.pPP_2?例如,它可能看起来像 namespace WpfApp4.pPP_2 { public class Components { public static Dictionary&lt;string, Module&gt; Modules { get; set; } } } 我已经在我的测试项目上进行了这个工作,所以我可能不会像你一样对 Dictionary Components 做一些事情。
  • 目前还不是解决方案,但您可以采取一些措施来消除其中一个潜在问题。将ComboBox.ItemTemplate(以及里面的所有内容)替换为DisplayMemeberPath="Name"。这让 ComboBox 知道显示 FeatureName 属性,而无需声明您自己的模板。无需担心的束缚。

标签: c# wpf .net-core combobox datagrid


【解决方案1】:

对于功能组合框,您似乎正在绑定到Modules 对象上的内部值下拉列表,并希望将该列表更改为一项……可以在哪里选择该项?这毫无意义。


要纠正问题,请执行以下步骤

  1. 首先,您需要在某处绑定一个静态(不变的)功能列表。
  2. Module 中删除 Features 并将其替换为 id 属性,为避免混淆,现在将其称为 FeatureName
  3. 使用DataGridComboBoxColumn,这将允许根据ID 更改一个值。再说一遍,可悲的是,Feature 类的 id 是Name。为了更现实,它应该是Feature 上的一个Id 数字字段,它可以识别和关联这种方式;如 #2 中所述,我们现在将我们的 id 称为 FeatureName 以避免混淆。

步骤 1 此步骤在您将加载的窗口(或页面或控件)数据连接(VM?)上设置名为 List&lt;string&gt;public 属性 FeatureList id 值 来自所有特征,例如这些字符串:{ "Heinzen", "Coolen", "Ein", "Klinen", "Yagermeisters", ... } 再次出现在 Strings 列表中(不是 Features)。

然后将该列表放在某个页面资源上,例如

<Window.Resources>

    <CollectionViewSource x:Key="FeatureList"
                          Source="{Binding FeatureList}" />

</Window.Resources> 

第 2 步Module 中删除public List&lt;Feature&gt; Features { get; set; } 并将其替换为public string FeatureName { get; set; }

第 3 步现在,您将使用 更文明 DataGridComboBoxColumn 替换之前有组合框的 Frankenstein DataGridTemplateColumn。这将允许显示和编辑/选择将选择/显示特征的值。

这样输入:

<DataGridComboBoxColumn Header="Feature"
                        SelectedItemBinding="{Binding FeatureName, Mode=TwoWay}"
                        ItemsSource="{Binding Source={StaticResource FeatureList}}"
                        Width="100" />

这应该让您对这个问题以及如何正确使用组合框有一个良好的开端。

【讨论】:

  • 我知道你是一名大学生......但请告诉我你在上面的代码中得到了Die Toten Hosen 引用作为幽默的旁注。 :-) 如果没有,我就老了。
  • 刚开始工作,所以我没有时间正确查看您的答案,但我发现您的想法与Die Toten Hosen tho 联系在一起。还没变老^^我会尝试解决方案并再次发表评论!
  • 好的,所以我无法从模块中删除功能列表,因为这些功能在程序启动时已解析到应用程序中。因此,当程序启动时,我获得了功能,并且每个模块都获得了已解析的功能列表。我相信这就是为什么整个编辑都不起作用的原因。还是受不了
  • 这些功能是模块独有的……还是所有模块的一个列表?如果所有功能都相同,那么您可以基于第一个模块的功能列表中提到的静态列表。但是选择下拉菜单必须从一个位置存储(并在其他时候获取它)它的值。这就是你必须解决的问题。
  • 因此必须将选择保存到Module 上的属性中。这是情况的症结所在。无法保存回功能列表...使用组合框通常用于选择一项。您将需要创建一个属性来保存该用户选择。这就是缺少的。如果您需要选择多个功能,您可能需要考虑用户选择的复选框列表。无论您的问题的症结在于 哪里 保存用户选择。如果不是选择。下拉菜单可能不是您最终需要的。
猜你喜欢
  • 2011-11-29
  • 2014-04-30
  • 1970-01-01
  • 1970-01-01
  • 2015-10-30
  • 2014-11-09
  • 1970-01-01
  • 1970-01-01
  • 2014-11-29
相关资源
最近更新 更多