帮助InvalidCastException

时间:2010-03-25 21:54:34

标签: c# winforms exception class casting

我有一个gridview,当双击一条记录时,我希望它为该特定记录打开一个新的详细视图表单。

例如,我创建了一个Customer类:

using System;
using System.Data;
using System.Configuration;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Collections;

namespace SyncTest
{
#region Customer Collection

public class CustomerCollection : BindingListView<Customer>
{
    public CustomerCollection() : base()
    {
    }

    public CustomerCollection(List<Customer> customers) : base(customers)
    {
    }

    public CustomerCollection(DataTable dt)
    {
        foreach (DataRow oRow in dt.Rows)
        {
            Customer c = new Customer(oRow);
            this.Add(c);
        }
    }
}

#endregion

public class Customer : INotifyPropertyChanged, IEditableObject, IDataErrorInfo
{
    private string _CustomerID;
    private string _CompanyName;
    private string _ContactName;
    private string _ContactTitle;
    private string _OldCustomerID;
    private string _OldCompanyName;
    private string _OldContactName;
    private string _OldContactTitle; 
    private bool _Editing;
    private string _Error = string.Empty;
    private EntityStateEnum _EntityState;
    private Hashtable _PropErrors = new Hashtable();

    public event PropertyChangedEventHandler PropertyChanged;

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

    public Customer()
    {
        this.EntityState = EntityStateEnum.Unchanged;
    }

    public Customer(DataRow dr)
    {
        //Populates the business object item from a data row
        this.CustomerID = dr["CustomerID"].ToString();
        this.CompanyName = dr["CompanyName"].ToString();
        this.ContactName = dr["ContactName"].ToString();
        this.ContactTitle = dr["ContactTitle"].ToString();

        this.EntityState = EntityStateEnum.Unchanged;
    }

    public string CustomerID
    {
        get
        {
            return _CustomerID;
        }
        set
        {
            _CustomerID = value;
            FirePropertyChangeNotification("CustomerID");
        }
    }

    public string CompanyName
    {
        get
        {
            return _CompanyName;
        }
        set
        {
            _CompanyName = value;
            FirePropertyChangeNotification("CompanyName");
        }
    }

    public string ContactName
    {
        get
        {
            return _ContactName;
        }
        set
        {
            _ContactName = value;
            FirePropertyChangeNotification("ContactName");
        }
    }

    public string ContactTitle
    {
        get
        {
            return _ContactTitle;
        }
        set
        {
            _ContactTitle = value;
            FirePropertyChangeNotification("ContactTitle");
        }
    }

    public Boolean IsDirty
    {
        get
        {
            return ((this.EntityState != EntityStateEnum.Unchanged) || (this.EntityState != EntityStateEnum.Deleted));
        }
    }

    public enum EntityStateEnum
    {
        Unchanged,
        Added,
        Deleted,
        Modified
    }

    void IEditableObject.BeginEdit()
    {
        if (!_Editing)
        {
            _OldCustomerID = _CustomerID;
            _OldCompanyName = _CompanyName;
            _OldContactName = _ContactName;
            _OldContactTitle = _ContactTitle;
        }
        this.EntityState = EntityStateEnum.Modified;
        _Editing = true;
    }

    void IEditableObject.CancelEdit()
    {
        if (_Editing)
        {
            _CustomerID = _OldCustomerID;
            _CompanyName = _OldCompanyName;
            _ContactName = _OldContactName;
            _ContactTitle = _OldContactTitle;
        }
        this.EntityState = EntityStateEnum.Unchanged;
        _Editing = false;
    }

    void IEditableObject.EndEdit()
    {
        _Editing = false;
    }

    public EntityStateEnum EntityState
    {
        get
        {
            return _EntityState;
        }
        set
        {
            _EntityState = value;
        }
    }

    string IDataErrorInfo.Error
    {
        get
        {
            return _Error;
        }
    }

    string IDataErrorInfo.this[string columnName]
    {
        get
        {
            return (string)_PropErrors[columnName];
        }
    }

    private void DataStateChanged(EntityStateEnum dataState, string propertyName)
    {
        //Raise the event
        if (PropertyChanged != null && propertyName != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        //If the state is deleted, mark it as deleted
        if (dataState == EntityStateEnum.Deleted)
        {
            this.EntityState = dataState;
        }
        if (this.EntityState == EntityStateEnum.Unchanged)
        {
            this.EntityState = dataState;
        }
    }
}

}

以下是双击事件的代码:

        private void customersDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
    {
        Customer oCustomer = (Customer)customersBindingSource.CurrencyManager.List[customersBindingSource.CurrencyManager.Position];
        CustomerForm oForm = new CustomerForm();
        oForm.NewCustomer = oCustomer;
        oForm.ShowDialog(this);

        oForm.Dispose();
        oForm = null;
    }

不幸的是,当此代码运行时,我收到一个InvalidCastException错误,指出“无法将对象强制转换为'System.Data.DataRowView'以键入'SyncTest.Customer'”。

此错误发生在该事件的第一行:

Customer oCustomer = (Customer)customersBindingSource.CurrencyManager.List[customersBindingSource.CurrencyManager.Position];

我做错了什么?......我该怎么做才能解决这个问题?非常感谢任何帮助。

谢谢!


编辑:

以下是填充数据的方式:

    private void Form1_Load(object sender, EventArgs e)
    {
        // TODO: This line of code loads data into the 'northwindDataSet.Customers' table. You can move, or remove it, as needed.
        this.customersTableAdapter.Fill(this.northwindDataSet.Customers);
    }

5 个答案:

答案 0 :(得分:1)

您的对象看起来类型为System.Data.DataRowView,而不是Customer。您的代码返回数据集而不是您期望的对象。您需要修改返回对象的代码。

答案 1 :(得分:0)

如何使用BindingSource.Current代替CurrentManager?但从它的外观来看,您的数据源是一个DataSet。

答案 2 :(得分:0)

private void customersDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
  DataGridView grid = (DataGridView) sender;
  Customer customer = (Customer) grid.Rows[e.RowIndex].DataBoundItem;
}

为简洁起见,删除了支票

答案 3 :(得分:0)

Customer oCustomer = (Customer) 
  ((DataRowView)customersBindingSource.Current).Row;

答案 4 :(得分:-1)

当您按照描述获得无效的强制转换时,由于对象不是您认为应该的类型。

您可以使用as关键字来避免异常。

Customer oCustomer = (Customer)customersBindingSource.CurrencyManager.List[customersBindingSource.CurrencyManager.Position];

变为

Customer oCustomer = customersBindingSource.CurrencyManager.List[customersBindingSource.CurrencyManager.Position] as Customer;

如果它是无效的强制转换,那么oCustomer将为空。

现在,如果您仍然获得null,则List中的对象不是Customer对象。我会使用调试器来确定对象是什么以及如何将其转换为Cusomter对象。

您将永远无法直接转换为Customer对象,因为您的错误是 InvalidCastException错误,指出“无法将对象强制转换为类型'System.Data.DataRowView'以键入'SyncTest.Customer'”。给你一个DataRowView对象。您需要取行并从行中提取值。