如何解决WPF中的“绑定表达式路径错误”问题?

4

我正在将一个可观察的模型对象集合绑定到数据网格。但是当我将绑定设置为集合时,我会收到指向属性的路径错误。

在调试此问题时,我检查了CustomerModel中的公共属性是否在DataGrid绑定中正确命名。同时也检查了返回给模型的集合不为空。我还检查了视图代码后台中的数据上下文是否设置正确。

我认为这可能是由于我在xaml中指定绑定路径的方式导致的错误。

每个字段的完整绑定错误详细信息如下:

System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName' property not found on 'object' ''MainViewModel' (HashCode=55615518)'. BindingExpression:Path=FirstName; DataItem='MainViewModel' (HashCode=55615518); target element is 'TextBox' (Name='fNameTbx'); target property is 'Text' (type 'String')

System.Windows.Data Error: 40 : BindingExpression path error: 'LastName' property not found on 'object' ''MainViewModel' (HashCode=55615518)'. BindingExpression:Path=LastName; DataItem='MainViewModel' (HashCode=55615518); target element is 'TextBox' (Name='lNameTbx'); target property is 'Text' (type 'String')

System.Windows.Data Error: 40 : BindingExpression path error: 'Email' property not found on 'object' ''MainViewModel' (HashCode=55615518)'. BindingExpression:Path=Email; DataItem='MainViewModel' (HashCode=55615518); target element is 'TextBox' (Name='emailTbx'); target property is 'Text' (type 'String')

有谁能指点我一下,进一步调试这个问题?

DataGrid的绑定路径和源如下所示:

                   <DataGrid Name="infogrid"
                              Grid.Row="0"
                              Grid.RowSpan="3"
                              Grid.Column="1"
                              Grid.ColumnSpan="3"
                              AutoGenerateColumns="False"
                              ItemsSource="{Binding Customers}"
                              SelectedItem="{Binding SelectedCustomer}">
                        <DataGrid.Columns>
                            <DataGridTextColumn Binding="{Binding Customers.Id}" Header="ID" />
                            <DataGridTextColumn Binding="{Binding Customers.FirstName}" Header="First Name" />
                            <DataGridTextColumn Binding="{Binding Customers.LastName}" Header="Last Name" />
                            <DataGridTextColumn Binding="{Binding Customers.Email}" Header="Email" />
                        </DataGrid.Columns>
                    </DataGrid>

视图模型包含一个类型为CustomerModel的可观察集合,称为Customers。这是我设置DataGrid ItemSource的内容。(为了易读性,我已删除VM中的其他代码)
namespace MongoDBApp.ViewModels
{

    class MainViewModel : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        private ICustomerDataService _customerDataService;


        public MainViewModel(ICustomerDataService customerDataService)
        {
            this._customerDataService = customerDataService;
            QueryDataFromPersistence();
        }



        private ObservableCollection<CustomerModel> customers;
        public ObservableCollection<CustomerModel> Customers
        {
            get
            {
                return customers;
            }
            set
            {
                customers = value;
                RaisePropertyChanged("Customers");
            }
        }



        private void QueryDataFromPersistence()
        {
            Customers = _customerDataService.GetAllCustomers().ToObservableCollection();

        }



        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }



    }
}

以下是CustomerModel中的字段,不确定为什么在绑定过程中找不到这些属性:
   public class CustomerModel : INotifyPropertyChanged
    {

        private ObjectId id;
        private string firstName;
        private string lastName;
        private string email;


        [BsonElement]
        ObservableCollection<CustomerModel> customers { get; set; }

        /// <summary>
        /// This attribute is used to map the Id property to the ObjectId in the collection
        /// </summary>
        [BsonId]
        public ObjectId Id { get; set; }

        [BsonElement("firstName")]
        public string FirstName
        {
            get
            {
                return firstName;
            }
            set
            {
                firstName = value;
                RaisePropertyChanged("FirstName");
            }
        }

        [BsonElement("lastName")]
        public string LastName
        {
            get
            {
                return lastName;
            }
            set
            {
                lastName = value;
                RaisePropertyChanged("LastName");
            }
        }

        [BsonElement("email")]
        public string Email
        {
            get
            {
                return email;
            }
            set
            {
                email = value;
                RaisePropertyChanged("Email");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

这是在视图的代码后台设置数据上下文的方法:

    public partial class MainView : Window
    {
        private MainViewModel ViewModel { get; set; }
        private static ICustomerDataService customerDataService = new CustomerDataService(CustomerRepository.Instance);


        public MainView()
        {
            InitializeComponent();
            ViewModel = new MainViewModel(customerDataService);
            this.DataContext = ViewModel;

        }

    }          

@EthanCabiac 刚刚编辑了帖子,包括了 XAML。 - Brian Var
1
我猜你在你的Window.DataContext上漏掉了一些东西,我复制了你的源代码并没有重现这个问题。同时,删除手动列定义中的AutoGenerateColumns="True"就足以让你的数据网格正常工作。 - Hossein Shahdoost
@HosseinShahdoost 我在我的问题中添加了代码,展示了我如何设置数据上下文。我对这里的问题感到困惑,网格绑定到MainVM中的Customer集合。然后,网格列绑定到该集合中的每个字段。但我仍然得到这个绑定路径表达式。我是否还应该在VM中定义每个模型的字段? - Brian Var
1
尝试使用常量数据填充您的可观察集合。从代码中删除CustomerDataService,并用以下内容填充它: Customers = new ObservableCollection<CustomerModel> { new CustomerModel() {FirstName = "myname", LastName = "myfamily"}, new CustomerModel() {FirstName = "yourname", LastName = "yourfamily"} }; - Hossein Shahdoost
@BrianJ 当然,给我看代码。我会告诉你问题所在。 - Hossein Shahdoost
显示剩余3条评论
5个回答

9
这些绑定错误与您的DataGrid无关。它们表明您在某个地方有3个名为fNameTbx、lNameTbx和emailTbx的TextBox。DataGrid不会生成带有Name属性的项,因此它不会导致这些绑定错误。在尝试读取绑定错误时,最好按分号拆分并倒序阅读,如here所示。例如,
System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName' property not found on 'object' ''MainViewModel' (HashCode=55615518)'. BindingExpression:Path=FirstName; DataItem='MainViewModel' (HashCode=55615518); target element is 'TextBox' (Name='fNameTbx'); target property is 'Text' (type 'String')
也可以这样阅读。
  • 目标属性是'Text' (类型为 'String')
  • 目标元素是'TextBox' (名称='fNameTbx');
  • DataItem='MainViewModel' (HashCode=55615518);
  • BindingExpression路径错误:在'object''MainViewModel' (HashCode=55615518)'上未找到'FirstName'属性。 BindingExpression:Path=FirstName;

意思是你的某个地方有

<TextBox Name="fNameTbx" Text="{Binding FirstName}" />

这个文本框的DataContext类型为MainViewModel,但是MainViewModel没有FirstName属性。

我建议在项目中搜索这些名称,或者您可以使用类似于 Snoop 的工具来调试运行时的数据绑定和 DataContext 问题。


我已经修复了那个错误,我必须将绑定设置为SelectedCustomer.FirstName等。我遇到了另一个问题,即从仓库中提取数据的数据服务,详见我的上面的评论。 - Brian Var
@BrianJ 如果您在从DataService获取记录方面遇到其他问题,最好另外开一个问题来讨论。这段代码和问题与您的第一个问题有关,因此您可能无法得到关于第二个问题所需的关注。 - Rachel

1
异常提示表明DataBinding引擎正在查找MainViewModel上的字段FirstNameLastName等,而不是CustomerModel
在列的单个绑定表达式中,您不需要指定属性Customers
<DataGrid.Columns>
  <DataGridTextColumn Binding="{Binding Id}" Header="ID" />
  <DataGridTextColumn Binding="{Binding FirstName}" Header="First Name" />
  <DataGridTextColumn Binding="{Binding LastName}" Header="Last Name" />
  <DataGridTextColumn Binding="{Binding Email}" Header="Email" />
</DataGrid.Columns>

我以前尝试过那个解决方案,设置 Binding="{Binding FirstName}" 等,但是我收到了错误信息: "System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName' property not found on 'object' ''MainViewModel' (HashCode=19160433)'. BindingExpression:Path=FirstName; DataItem='MainViewModel' (HashCode=19160433); target element is 'TextBox' (Name='fNameTbx'); target property is 'Text' (type 'String')" 你还有其他的想法吗? - Brian Var
@BrianJ 所以无论您是否使用 Customers.,您都会得到完全相同的错误? - Ethan Cabiac
是的,如果我使用Customer.FirstName或者FirstName,所有字段都会出现这个错误。我没有在VM中定义单独的属性,而是将数据网格绑定到了一种名为CustomerModel的可观察集合上,该类型实现了INPC接口,在我的代码中你可以看到^^ - Brian Var
我看到你正在将DataGrid绑定到“Customers”属性,但错误消息显示绑定引擎正在VM上查找这些属性(显然在那里不存在) 。 - Ethan Cabiac
1
我还注意到你正在使用 AutoGenerateColumns="True",但是你又手动定义了列? - Ethan Cabiac
好的,我已将该属性更正为AutoGenerateColumns="False",我已将数据上下文代码添加到了我的问题上方。我的理解是将网格的ItemSource设置为Customer集合,该集合位于该视图的MainVM数据上下文中。然后该集合中的属性将可用于UI?您能否就我的错误提供建议.. - Brian Var

0

当我在DataTemplate中使用TextBlock Text Binding时,遇到了同样的问题,最终我不得不这样做:

Text={Binding DataContext.SuccessTxt}

尝试在属性前添加"DataContext."并查看其是否能正常工作。

0
public Window()
{
      this.DataContext = this;
      InitializeComponent();
}
public string Name {get;set;}
//xaml
<TextBlock Text="{Binding Name}"/>

InitializeComponent() 之前加上 this.DataContext = this;,以确保在加载 XAML 时 DataContext 可用。

Name 属性应该是 public 并且带有 { get; }
(如果是私有的,则 WPF 无法访问)

0

我曾经遇到过同样的问题,解决方法是使用属性而不是类字段。类字段似乎在绑定方面存在问题。也许你应该在你的视图模型中使用属性而不是字段。

// This field not working

public SolidColorBrush BrushColor;

// But this property the binding worked

public SolidColorBrush BrushColor { get; set; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接