简体   繁体   English

BindingList,DataGridView和SQL过程

[英]BindingList, DataGridView and SQL Procedures

I'm trying to build simple data editor. 我正在尝试构建简单的数据编辑器。
I've created simple application that uses DataGridView to edit data. 我创建了使用DataGridView编辑数据的简单应用程序。
To hold my data objects I'm using BindingList. 为了保存我的数据对象,我使用的是BindingList。 This way after adding new items my grid is able to show that new entry. 这样,在添加新项目之后,我的网格便可以显示该新条目。
My form is working well, but now I must connect some data to it. 我的表单运行良好,但是现在我必须将一些数据连接到它。
While loading is quite easy I have problem with adding new elements and updating. 虽然加载非常容易,但是我在添加新元素和更新时遇到了问题。

I know that I could use SqlDataAdapter and DataTable, but I would like to use BindingList and automatically save all changes using stored procedures. 我知道我可以使用SqlDataAdapter和DataTable,但是我想使用BindingList并使用存储过程自动保存所有更改。

I've created some model classes: 我创建了一些模型类:

public class Phone : INotifyPropertyChanged
{
    #region AUTO
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
    #endregion

    public int PhoneId { get; set; }
    public string Number { get; set; }
    public string Type { get; set; }
    public string TypeTxt { get; set; }

    private bool _valid;
    public bool Valid
    {
        get { return _valid; }
        set { SetField(ref _valid, value, "Valid"); }
    }
}

Right now I only need to catch Valid change so I'm catching only this property change. 现在,我只需要捕获有效更改,因此仅捕获此属性更改。

public class PhonesList : BindingList<Phone>
{
    public void AddNew(Phone newPhone)
    {
        //here I could call my sql procedure
        Add(newPhone);
    }
}

This class stores my phones, as in comments I could catch add inside AddNew method, but this way I must use AddNew instead of Add 此类存储了我的电话,就像注释中我可以在AddNew方法中捕获add一样,但是这种方式我必须使用AddNew而不是Add

And inside my main form: 在我的主要形式内:

    private readonly int _userId;
    private PhonesList _phones;

    private BindingSource _gridSource;

    private BindingSource GridSource
    {
        get { return _gridSource ?? (_gridSource = new BindingSource()); }
    }

    public PhoneDetails(int userId)
    {
        _userId = userId;
        InitializeComponent();
    }

    private void PhoneDetails_Load(object sender, EventArgs e)
    {
        if (_applicationId == 0) return;
        _phones = DB.Instance.LoadPhones(_userId);

        GridSource.DataSource = _phones;
        phonesGV.AutoGenerateColumns = false;
        phonesGV.DataSource = GridSource;
        _phones.ListChanged += _phones_ListChanged;
        _phones.RaiseListChangedEvents = true;
        _phones_ListChanged(null, null);
    }

    void _phones_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e)
    {
        Text = string.Format("Phones - count: {0}", _phones.Count);
        Refresh();
    }

    private void addNew_Click(object sender, EventArgs e)
    {
        errorProvider1.Clear();
        if(newPhoneNumberTb.Text.Length<9)
        {
            errorProvider1.SetError(newPhoneNumberTb,"9 digits minimum!");
            return;
        }
        if (newPhoneTypeCb.SelectedItem==null)
        {
            errorProvider1.SetError(newPhoneTypeCb, "Choose phone type!");
            return;
        }
        _phones.AddNew(new Phone
            {
                Number = newPhoneNumberTb.Text.Trim(),
                PhoneId = 0,
                Type = newPhoneTypeCb.SelectedItem.ToString(),
                TypeTxt = newPhoneTypeCb.SelectedItem.ToString(),
                Valid = true
            });
        newPhoneNumberTb.Text = "";
        newPhoneTypeCb.SelectedItem = null;
    }

I'm able to load data into my form using stored procedure, but right now I would like to call stored procedure that add new phone and update it when necessary. 我可以使用存储过程将数据加载到表单中,但是现在我想调用存储过程,以添加新电话并在必要时进行更新。

Where should I listen for add/update "events"? 我应该在哪里收听添加/更新“事件”?
Is it correct to add add/update functionality to models? 向模型添加添加/更新功能是否正确?

Ideally I could add add/update to Phone Model, but this way I'll have problem with loading data, because every time I'll create instance my 'Add' query will be called. 理想情况下,我可以向电话模型中添加添加/更新,但是这样一来,我将无法加载数据,因为每次创建实例时,都会调用“添加”查询。

Here is my LoadPhones: 这是我的LoadPhone:

    public PhonesList LoadPhones(int userId)
    {
        var phones = new PhonesList();

        using (var conn = new SqlConnection(ConnStr))
        {
            using (var cmd = new SqlCommand(@"LoadTelefonow", conn))
            {
                cmd.Parameters.Add("@USER_ID", SqlDbType.Int).Value = userId;
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandTimeout = 360;
                conn.Open();
                using (SqlDataReader sdr = cmd.ExecuteReader())
                {
                    while (sdr.Read())
                    {
                        var phone = new Phone
                        {
                            PhoneId = Convert.ToInt32(sdr["Tel_Id"]),
                            Number = Convert.ToString(sdr["Number"]),
                            Type = Convert.ToString(sdr["Typ"]),
                            TypeTxt = Convert.ToString(sdr["Typ"]),
                            Valid = Convert.ToBoolean(sdr["Status"])
                        };
                        phones.Add(phone);
                    }
                }
                conn.Close();
            }
        }
        return phones;
    }

So my question is: Where and how should I add adding and updating functionality to my BindingList of my Phone model (don't know which one would be better)? 所以我的问题是:我应该在哪里以及如何向我的Phone模型的BindingList中添加添加和更新功能(不知道哪一个更好)?

To Update: 更新:

Using BindingSource as the DataGridView 's DataSource is good to be notified when a property changes inorder to update the corresponding item. 使用BindingSource作为DataGridViewDataSource可以很好地在属性更改时得到通知,以更新相应的项目。 You can do something like this: 您可以执行以下操作:

In your MainForm or through designer: 在您的MainForm中或通过设计器:

datagridview1.DataSource = bindingSource1;
bindingSource1.CurrentItemChanged += new EventHandler(bindingSource1_CurrentItemChanged);

Declate a field in your form to maintain a list of changed items: 在表单中声明一个字段,以维护已更改项目的列表:

private List<int> UpdatedItemsIndex;

And add to it when something changes: 并在发生更改时将其添加到其中:

private void bindingSource1_CurrentItemChanged(object sender, EventArgs e)
{
    UpdatedItemsIndex.Add(bindingSource1.IndexOf(bindingSource1.Current));
}

To Add: Likewise, use BindingSource and handles AddNew 要添加:同样,使用BindingSource并处理AddNew

bindingSource1.AddingNew += new System.ComponentModel.AddingNewEventHandler(this.bindingSource1_AddingNew);

And: 和:

List<int> AddedItemsIndex = new List<int>();
private void bindingSource1_AddingNew(object sender, AddingNewEventArgs e)
{
    AddedItemsIndex .Add(bindingSource1.Count);
}

To Save Changes : Add/Update based on the lists. 保存更改 :根据列表添加/更新。 Remeber to clear them after they are inserted/updated. 请记住在插入/更新它们后清除它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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