简体   繁体   中英

The bidirectional binding requires "Path" or "XPath" exception. Windows WPF

In a Datagrid which looks like this I am getting an exception:

<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>

So far so good almost everything works fine. But, when i select on Item on my ComboBox :

在此处输入图片说明

I get the exception:

System.InvalidOperationException: "Die bidirektionale Bindung erfordert "Path" oder "XPath"."

The C# Code behind is an Object, which Contains a List of Features ( List<Feature> ), which contains Feature s. I initialize it like this:

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

Edit: The Module Class:

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;
            }
        }
    }

The Feature Class:

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; }
    }

Property Class:

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

For the features combobox it appears you are binding to an internal drop down of values on the Modules object and wanting to change that list to one item... where that one can be selected? This makes no sense.


To rectify the issue do these steps

  1. First off you need a static (unchanging) list of features somewhere to bind to.
  2. Remove Features from Module and replace it with an id property, right now to avoid confusion call it FeatureName .
  3. Use a DataGridComboBoxColumn which will allow for one value to be changed based on an id. To say again, sadly, the id on the Feature class is Name . For to be more realistic it should be an Id number field on Feature which could identify and associate that way; as mentioned in #2 we will call our id FeatureName for now to avoid confusion.

Step 1 This step sets up a public property of List<string> named FeatureList on your window's (or page, or control's) datacontect (a VM?) where you will have loaded the id values from all features such as these strings: { "Heinzen", "Coolen", "Ein", "Klinen", "Yagermeisters", ... } in again, that list of String s (not Feature s).

Then put that list on a page resources somewhere such as

<Window.Resources>

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

</Window.Resources> 

Step 2 Remove from Module public List<Feature> Features { get; set; } public List<Feature> Features { get; set; } public List<Feature> Features { get; set; } and replace it with public string FeatureName { get; set; } public string FeatureName { get; set; }

Step 3 Now you will replace the Frankenstein DataGridTemplateColumn where you had a combobox with a more civilized DataGridComboBoxColumn . Which will allow for the display and editing/selecting of the value which will choose/display the feature.

Put this in as such:

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

This should give you a good start on the issue and how to properly use a combobox.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM