シンプルなデータエディタを構築しようとしています。
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 に追加機能と更新機能をどこにどのように追加すればよいですか (どちらが優れているかわかりません)。