Помощь с InvalidCastException - PullRequest
       43

Помощь с InvalidCastException

3 голосов
/ 26 марта 2010

У меня есть сетка, и когда дважды щелкают запись, я хочу, чтобы она открыла новую форму подробного просмотра для этой конкретной записи.

В качестве примера я создал класс 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];

Что я делаю не так? ... и что я могу сделать, чтобы это исправить? Любая помощь с благодарностью.

Спасибо!


EDIT:

Вот как заполняются данные:

    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 ]

1 голос
/ 26 марта 2010

Похоже, ваш объект имеет тип System.Data.DataRowView, а не Customer. Ваш код возвращает набор данных вместо ожидаемых объектов. Вам нужно изменить код, который возвращает ваши объекты.

0 голосов
/ 10 июня 2010
Customer oCustomer = (Customer) 
  ((DataRowView)customersBindingSource.Current).Row;
0 голосов
/ 26 марта 2010
private void customersDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
  DataGridView grid = (DataGridView) sender;
  Customer customer = (Customer) grid.Rows[e.RowIndex].DataBoundItem;
}

Для краткости сняты чеки

0 голосов
/ 26 марта 2010

Как насчет использования BindingSource.Current вместо CurrentManager? Но, судя по всему, вашим источником данных является DataSet.

0 голосов
/ 26 марта 2010

Когда вы получаете неверное приведение, как вы описали, это связано с тем, что объект не того типа, который, как вы думаете, должен быть.

Вы можете избежать исключения, используя в качестве ключевое слово.

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

становится

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

Если это неверное приведение, то oCustomer будет нулевым.

Теперь, если вы все еще получаете нулевое значение, тогда объектиз списка не является объектом Customer.Я бы использовал отладчик, чтобы определить, что это за объект и как вы будете приводить его к объекту Cusomter.

Вы никогда не сможете выполнить непосредственное преобразование в объект Customer, поскольку ваша ошибка - ошибка InvalidCastException с указанием ошибкиНевозможно привести объект к типу " System.Data.DataRowView ", чтобы ввести "SyncTest.Customer" ".дает вам объект DataRowView.Вам нужно взять строку и вытащить значения из строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...