1

シンプルなデータエディタを構築しようとしています。
DataGridView を使用してデータを編集する簡単なアプリケーションを作成しました。
データ オブジェクトを保持するために、BindingList を使用しています。このようにして、新しいアイテムを追加した後、グリッドはその新しいエントリを表示できます。
フォームはうまく機能していますが、データを接続する必要があります。
読み込みは非常に簡単ですが、新しい要素の追加と更新に問題があります。

SqlDataAdapter と DataTable を使用できることはわかっていますが、BindingList を使用し、ストアド プロシージャを使用してすべての変更を自動的に保存したいと考えています。

いくつかのモデル クラスを作成しました。

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

現在、有効な変更のみをキャッチする必要があるため、このプロパティの変更のみをキャッチしています。

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

addこのクラスは、メソッド内でキャッチできるコメントのように、電話を保存しますAddNewが、この方法ではAddNew代わりに使用する必要がありますAdd

そして私のメインフォーム内:

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

ストアド プロシージャを使用してフォームにデータを読み込むことができますが、現在、新しい電話を追加して必要に応じて更新するストアド プロシージャを呼び出したいと考えています。

「イベント」の追加/更新はどこでリッスンする必要がありますか?
モデルに追加/更新機能を追加することは正しいですか?

理想的には、電話モデルに追加/更新を追加できますが、この方法では、インスタンスを作成するたびに「追加」クエリが呼び出されるため、データの読み込みに問題が発生します。

これが私の 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;
    }

だから私の質問は次のとおりです。電話モデルの BindingList に追加機能と更新機能をどこにどのように追加すればよいですか (どちらが優れているかわかりません)。

4

1 に答える 1

1

更新するには:

BindingSourceとして使用すると、対応するアイテムを更新するためにプロパティが変更されたときに通知を受けることができますDataGridViewDataSource次のようなことができます。

MainForm またはデザイナーを介して:

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

フォームでフィールドを宣言して、変更された項目のリストを維持します。

private List<int> UpdatedItemsIndex;

何かが変更されたときに追加します。

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

追加するには: 同様に、BindingSourceAddNew を使用して処理します。

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

と:

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

変更を保存するには:リストに基づいて追加/更新します。それらが挿入/更新された後、それらをクリアすることを忘れないでください。

于 2013-09-30T07:55:41.547 に答える