8

DataSourceUpdateMode = Neverを設定してバインディングデータソースの自動更新をオフにしてから、ボタンを使用してロット全体を更新すると(binding.WriteValueを使用)、問題が発生します。つまり、最初のバインドされたコントロールのデータソースのみが更新されます。他のすべてのコントロールは元の値にリセットされます。

これは、現在のオブジェクトが変更されたときに(上記のWriteValueの後に発生するように)、ControlUpdateMode = OnPropertyChangeの場合、他のすべてのコントロールがデータソースから値を再読み込みするためです。

この問題を回避するための標準的な方法は何ですか?

1つの方法は、BindingSourceからクラスを派生させ、WriteAllValuesメソッドを追加することです。このメソッドは次のことを行います。

(1)バインディングごとに、ControlUpdateModeを保存します

(2)バインディングごとに、ControlUpdateMode=Neverを設定します

(3)バインディングごとに、WriteValueメソッドを呼び出します

(4)バインディングごとに、ControlUpdateModeを保存された値にリセットします

(5)バインディングごとに、ControlUpdateMode = OnPropertyChangeの場合、ReadValueメソッドを呼び出します。

これを行うことで何か問題がありますか?

独自のクラスを使用している場合、IEditableObjectを実装すると問題は解決しますか?

私が取り組んでいる別のコントロールでは、独自のバインディングを実装しています。その中で私が問題を回避する方法は、次のコードを使用することです。(私は最低限を入れました、あなたがそれに従うことができることを願っています!):

Private Shared ControlDoingExplicitUpdate As MyCustomControl = Nothing

Private Sub UpdateDataSourceFromControl(ByVal item As Object, ByVal propertyName As String, ByVal value As Object)
  Dim p As PropertyDescriptor = Me.props(propertyName)
  Try
    ControlDoingExplicitUpdate = Me
    p.SetValue(item, value)
  Catch ex As Exception
    Throw
  Finally
    ControlDoingExplicitUpdate = Nothing
  End Try
End Sub

Private Sub DataBindingSource_CurrentItemChanged(ByVal sender As Object, ByVal e As System.EventArgs)
  If (ControlDoingExplicitUpdate IsNot Nothing) AndAlso (ControlDoingExplicitUpdate IsNot Me) Then Exit Sub
  Me.UpdateControlFromDataSource() 'Uses ReadValue
End Sub

したがって、UpdateDataSourceFromControlが呼び出されると、すべてのCurrentItemChangedイベントが、同じBindingSource内の他のすべてのコントロールに対して呼び出されます。ただし、ControlDoingExplicitUpdateが設定されているため、更新を行ったコントロールでない限り、データソースから値を再読み込みすることはありません。これらのイベントがすべて完了した後、ControlDoingExplicitUpdateはNothingに設定されるため、通常のサービスが再開されます。

私はあなたがこれに従うことができることを願っています、そして-もう一度-私は尋ねます、あなたはこれに関する何か問題を見ることができますか?

4

3 に答える 3

5

フォームについても同様の要件があります。私の場合、フォームの[保存]ボタンをクリックしたときに、すべてのフォームのコントロールのデータバインディングが発生するようにしたいだけでした。

私が見つけた最善の解決策は、各バインディングのDataSourceUpdateModeをOnValidationに設定してから、含まれているフォームのAutoValidateプロパティをDisableに設定することでした。これにより、フォーム上のコントロール間でフォーカスを変更するときにバインドが防止されます。次に、[保存]ボタンのClickイベントで、フォームの入力を手動で検証し、問題がない場合は、フォームのValidateChildrenメソッドを呼び出してバインディングをトリガーします。

この方法には、入力の検証方法を完全に制御できるという利点もあります。WinFormsには、デフォルトでこれを行うための適切な方法が含まれていません。

于 2011-08-26T15:58:19.040 に答える
2

私は最近、これが答えとして与えられたstackoverflowについて読んだと思います: 双方向データバインディングを無効にする

public static class DataBindingUtils
{
    public static void SuspendTwoWayBinding( BindingManagerBase bindingManager )
    {
        if( bindingManager == null )
        {
           throw new ArgumentNullException ("bindingManager");
        }

        foreach( Binding b in bindingManager.Bindings )
        {
            b.DataSourceUpdateMode = DataSourceUpdateMode.Never;
        }
    }

    public static void UpdateDataBoundObject( BindingManagerBase bindingManager )
    {
        if( bindingManager == null )
        {
           throw new ArgumentNullException ("bindingManager");
        }

        foreach( Binding b in bindingManager.Bindings )
        {
            b.WriteValue ();
        }
    }
}
于 2015-03-03T16:05:13.757 に答える
0

データバインディングと戦わないことをお勧めします。DataSourceUpdateModeをOnValidationとして保持します。次に、次の2つのオプションのいずれかを選択します。

1、コントロールの値を変更する前に、バックアップの現在の値を作成します。ユーザーが[キャンセル]ボタンをクリックした場合は、バックアップされた値をデータソースにコピーして戻します。そして、userBindingSource.ResetCurrentItem()を実行して、コントロールの値を元の値に更新します。

2、ユーザーが[キャンセル]ボタンをクリックした場合、データベースからIDで新しいオブジェクトをプルします。そして、新しいオブジェクトを使用して、バインディングソースの現在のオブジェクトを置き換えます。コードは次のようになります。

MyObject myObject = myObjectBindingSource.Current as MyObject;
MyObject originalObject = myObjectRepository.GetOneObjectFromDatabase(myObject.ID);
int currentIndex = myObjectBindingSource.Position;
myObjectBindingSource.Insert(currentIndex, originalObject);
myObjectBindingSource.Position = currentIndex;
myObjectBindingSource.RemoveAt(currentIndex+1);

2番目のオプションは、オブジェクトをコピーする作業を回避するため、個人的に気に入っています。各プロパティをコピーする必要があり、将来プロパティが変更された場合にメンテナンスが難しくなる可能性があります。また、最新のデータを取得するため、レコードが非常に新鮮になります。また、最初のオプションでは、レコードのコピーが1つだけ保存されます。他のレコードに移動して他の変更を加えると、コピーは失われます。ただし、2番目のオプションはデータベースからデータを取得するため、以前に変更されたがまだ保存されていないレコードにいつでも戻ることができ、キャンセルボタンをクリックして元の値に戻すことができます。

于 2019-10-28T20:05:14.367 に答える