2

BindingSource.AddingNewイベントハンドラー内のアイテムの追加をキャンセルすることはできますか?

ユーザーが自分の[新規追加]ボタンをクリックするとBindingNavigator、有効なファイルが返される場合と返されない場合があるダイアログが開きます。今、私はこのようなものを持っています:

void bindingSource_AddingNew(object sender, AddingNewEventArgs e)
{
    using (var dialog = new OpenFileDialog())
    {
        var result = dialog.ShowDialog();

        // user canceled?
        if (result == DialogResult.Cancel)
            return;

        // TryLoad will return null on failure
        var data = TryLoad(dialog.FileName);

        // only add the item to the grid if not null
        if (data != null)
            e.NewObject = data;
    }
}

e.NewObjectハンドラー内の値を設定しなくても、新しい(「空の」)アイテムがDataGridViewに表示されます。

アイテムの追加をキャンセルすることはできますか?

4

7 に答える 7

5

BindingSourceがICancelAddNewインターフェイスを実装している場合は、新しく追加されたオブジェクトに対してCancelNewを呼び出して元に戻すことができるはずです。AddNewのイベントハンドラーでこれを試すことはお勧めしません。このインターフェースを使用することにより、アイテムは引き続きリストに追加されますが、EndNew()がトランザクションをコミットし、CancelNew()がトランザクションを元に戻す保留状態になります。BindingListはICancelNewを実装しているようで、次のようなことができます。

public void MyFunctionWhereIAddNew()
{
    var item  = _myBindingSource.AddNew();

    item.SetSomeParams(...);

    if(item.CheckItemForSuccess() != true)
    {
        _myBindingSource.CancelNew(_myBindingSource.IndexOf(item));
    }
}

独自のICancelNewの実装方法に関するリンクが必要な場合は、この古いブログ投稿を確認してください。

于 2012-10-02T13:25:52.163 に答える
3

簡単な解決策:

  1. プロパティウィンドウでBindingNavigatorの「AddNewItem」プロパティをクリアして、bindingsourceAddingNewを起動しないようにします。
  2. bindingNavigatorのプラス記号をダブルクリックして、プラスボタンのClickイベントを生成し、次のように新しいアイテムの追加手順を手動で制御します。

    private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
    {
        using (var dialog = new OpenFileDialog())
        {
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                var data = TryLoad(dialog.FileName); ;
    
                if (data != null)
                {
                    myBindingSource.Add(data);
                }
            }
        }
    }
    
于 2012-10-08T21:15:18.923 に答える
2

プロダクションのようなものにする前に、間違いなくいくつかの追加が必要な1つの簡単な解決策は、バインディングナビゲーターのAd​​dNewクリックイベントでの編集をキャンセルすることです。

編集をキャンセルすることが目的であるかどうかを示すブール値をbindingSource_AddingNew(..)に設定する必要があります。

     
private void bindingNavigatorAddNewItem_Click(object sender、EventArgs e)
{{       
    if(cancelEdit)
        bindingSource.CancelEdit();
}
于 2012-10-09T11:13:16.050 に答える
2

それは可能ですが、非常に醜い方法です。の追加ボタンのクリックイベントを上書きする必要がありますBindingNavigator。以下に示すソリューションはテストと動作を行いますが、実稼働システムには明らかに適していません。本番システムには、イベントハンドラーを並べ替えるためのこのようなコードが1つあります。私はそれが好きではありませんが、それは機能します。

public partial class Form1 : Form
{
    public MethodInfo refreshMethod;
    public Form1()
    {
        InitializeComponent();

        // Build Data
        var list = new List<MyData>
            {
                new MyData {Id = 1, Str = "1"},
                new MyData {Id = 2, Str = "2"}
            };

        //Bind Data
        bindingSource1.DataSource = list;
        dataGridView1.DataSource = bindingSource1;
        bindingNavigator1.BindingSource = bindingSource1;

        // get event handler storage property
        var eventsProperty = bindingNavigator1.AddNewItem.GetType().GetProperty(
            "Events",
            BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance
            );

        // get key for click event
        var clickField = bindingNavigator1.AddNewItem.GetType().GetField(
            "EventClick",
            BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Static
            );

        var clickKey = clickField.GetValue(null);

        // find refresh method
        refreshMethod = bindingNavigator1.GetType().GetMethod(
            "RefreshItemsInternal",
            BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance
            );

        // get storage instance
        var handlers = (EventHandlerList)eventsProperty.GetValue(bindingNavigator1.AddNewItem, null);
        // find click event handlers
        var clickEventHandlers = handlers[clickKey];

        // remove current handlers
        var handlerInvocationList = clickEventHandlers.GetInvocationList();
        for (int index = 0; index < handlerInvocationList.Length; index++)
            handlers.RemoveHandler(clickKey, handlerInvocationList[index]);

        // attach our new handler
        handlers.AddHandler(clickKey, new EventHandler(NewAddNewHandler));
    }

    private void NewAddNewHandler(object sender, EventArgs e)
    {
        if (bindingNavigator1.Validate() && null != bindingNavigator1.BindingSource)
        {
            var result = MessageBox.Show("Add new?", "Are you..", MessageBoxButtons.YesNo) == DialogResult.Yes;

            if (!result)
                return;

            bindingNavigator1.BindingSource.AddNew();
            refreshMethod.Invoke(bindingNavigator1, null);
        }
    }

}
于 2012-10-05T09:12:26.937 に答える
1

ボタンで追加を処理できますか?その場合、DataGridViewのAddメソッドを呼び出す前に、ボタンクリックイベントを設定してすべてのパラメーターをチェックできます。

于 2012-10-08T15:20:40.813 に答える
0

一部のデータソースのテーブルからデータを追加または編集するためのダイアログフォームを表示している場合はBindingSource.CancelEdit()、いつでも関数を使用して、新しい行の追加をキャンセルし、BindingSource.EndEdit()アップロードに有効な入力データの編集を受け入れて終了することができます。たとえば、データベースで、追加/編集ダイアログフォーム(テキストボックスがcontactsBindingSourceにバインドされている)で次のコード行を使用します。

Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
    contactsBindingSource.EndEdit()
    contactsTableAdapter.Update(contactsTable)
    contactsTable = contactsTableAdapter.GetData()
End Sub

Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
    contactsBindingSource.CancelEdit()
    contactsTable = contactsTableAdapter.GetData()
End Sub
于 2015-10-28T13:35:00.010 に答える
0

私の提案は、BindingSourceから継承されたクラスのAddNewメソッドをオーバーライドすることです。

public override object AddNew() {
{
  if (CreateNewItem( out newItem))
  {
    base.Add(newItem);
    return newItem;
  }
  return null;
}
于 2020-08-25T11:14:12.860 に答える