2017-03-09 9 views
0

MVCモデルのビューレイヤーとモデル/アダプターレイヤー間を行き来するための正しいアプローチを見つけようとしています。以下は私の問題の擬似コードであり、私がそれをしたいものです。説明については、MyAdapter.ImportStuffメソッドのコメントを参照してください。コントローラ/アダプタが実際に静的なクラスですので、モデル/アダプタレイヤーの長いプロセスでビューレイヤーに情報を渡す方法

public class MyView : System.Windows.Forms.UserControl 
{ 
    private MyContoller Ctrl = new MyContoller(); 
    public MyView() 
    { 
    } 

    private void OnButtonClick() 
    { 
     Ctrl.DoSqlStuffNow(); 
     TellUserImportFinished(); 
    } 

    public void TellUserThingsHaveBeenDeleted() 
    { 
     this.label1.Text = "Stuff deleted..."; 
    } 
    public void TellUserHowManyRowsHaveBeenInserted(int rowCount) 
    { 
     this.label2.Text = $"Number of rows inserted: {rowCount}..."; 
    } 
    public void TellUserComplexQueriesAreDone() 
    { 
     this.label3.Text = "Complex queries are done..."; 
    } 
    public void TellUserImportFinished() 
    { 
     System.Windows.Forms.MessageBox.Show("Success!"); 
    } 
} 
internal class MyContoller 
{ 
    MyAdapter Adpt = new MyAdapter(); 
    internal void DoSqlStuffNow() 
    { 
     object someParameter = new object(); 
     Adpt.ImportStuff(someParameter); 
    } 
} 
internal class MyAdapter 
{ 
    internal void ImportStuff(object someParameter) 
    { 
     SqlConnection sqlConnection = new SqlConnection("connection"); 

     // All of this has to happen in one connection/transaction. 
     // It should not be broken into multiple methods 

     DeleteFromTable1(); 
     DeleteFromTable2(); 
     // Now I want to tell the user delete is complete! 

     MakeTempTable(); 
     InsertIntoTempTable(someParameter); 
     int rowCount = ImportIntoTable1(); 
     // Now I want to tell the user how many rows were just inserted! 

     DoComplexQuery(); 
     DoAnotherComplexQuery(); 
     // Now I want to tell the user complex queries are done! 

     ImportIntoTable2(); 
     DropTempTable(); 
     // Presumably, I can say "success" when this function returns, which is fine 
    } 
} 

私の特定のケースはさらに悪くなるので、イベントのは、対処するのも楽しいではありませんが、私はこの単純な場合には、それを処理するために最善の方法さえわかりません。

アドバイスをいただければ幸いです!

答えて

0

私はものを複雑にすることはありません。デザインを見ると、アダプタクラスのイベントとMyViewのバインディングがあります。

通知する内容に基づいて4つの予定を作成します。 1つの方法ですべてが起こっているので、1つのイベントと4つの異なるステータスを持つこともできます。しかし、イベントハンドラの後半にはIFの束が必要なので、私はこのアプローチが嫌いです。

もちろん、独自の代理人も書くことができますが、わかりやすくするためにEventHandlerクラスを使用しました。

public event EventHandler DeleteCompleted; 

    //int: the number of rows inserted 
    public event EventHandler<int> RowsInserted; 

    public event EventHandler ComplexQuerycCompleted; 

    //bool: if the operation completed successfully. 
    public event EventHandler<bool> OperationCompleted; 

複数のイベントのもう一つの利点は、それがのアプリの一部にのみ作動が完了したときに知りたいが、他に何もあなただけのその特定のイベントをサブスクライブしないだろうと言ってみましょうです。

必要に応じてイベントを呼び出すようにクラスを変更します。

internal class MyAdapter 
{ 

    public event EventHandler DeleteCompleted; 

    public event EventHandler<int> RowsInserted; 

    public event EventHandler ComplexQuerycCompleted; 

    public event EventHandler<bool> OperationCompleted; 


    internal void ImportStuff(object someParameter) 
    { 
     SqlConnection sqlConnection = new SqlConnection("connection"); 

     // All of this has to happen in one connection/transaction. 
     // It should not be broken into multiple methods 

     DeleteFromTable1(); 
     DeleteFromTable2(); 
     // Now I want to tell the user delete is complete! 

     this.DeleteCompleted?.Invoke(this, new EventArgs()); 

     MakeTempTable(); 
     InsertIntoTempTable(someParameter); 
     int rowCount = ImportIntoTable1(); 

     // Now I want to tell the user how many rows were just inserted! 
     this.RowsInserted?.Invoke(this, rowCount); 

     DoComplexQuery(); 
     DoAnotherComplexQuery(); 

     // Now I want to tell the user complex queries are done! 
     this.ComplexQuerycCompleted.Invoke(this, new EventArgs()); 

     ImportIntoTable2(); 
     DropTempTable(); 

     // Presumably, I can say "success" when this function returns, which is fine 
     this.OperationCompleted?.Invoke(this, true); 
    } 
} 

あなたのMyControllerクラスでは、必要なイベントを購読することができます。このクラスでは、アダプタからの変更についてMyViewビューに通知するように、INotifyPropertyChanged(MVVM)を実装できます。

internal class MyContoller : INotifyPropertyChanged 
{ 
    MyAdapter Adpt = new MyAdapter(); 

    public event PropertyChangedEventHandler PropertyChanged; 

    private int rowsInserted; 
    public int RowsInserted 
    { 
     get { return rowsInserted;} 
     set 
     { 
      if (rowsInserted == value) 
       return; 

      rowsInserted = value; 
      RaisedPropertyChanged(nameof(RowsInserted)); 
     } 
    } 

    internal MyContoller() 
    { 
     //Remember to remote the event subscriptions calling: 
     // Adpt.RowsInserted -= OnRowsInserted 
     Adpt.RowsInserted += OnRowsInserted; 
    } 

    internal void DoSqlStuffNow() 
    { 
     object someParameter = new object(); 
     Adpt.ImportStuff(someParameter); 
    } 

    /// <summary> 
    /// Raiseds the property changed. 
    /// </summary> 
    /// <param name="propertyName">Property name.</param> 
    protected void RaisedPropertyChanged([CallerMemberNameAttribute] string propertyName = "") 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    /// <summary> 
    /// Called when the Rows has been inserted in the <see cref="MyAdapter"/> 
    /// </summary> 
    /// <param name="sender">Sender</param> 
    /// <param name="numberOfRows">The Number of rows in inserted</param> 
    void OnRowsInserted(object sender, int numberOfRows) 
    { 
     //Notify the UI about objects inserted 
     RowsInserted = numberOfRows; 
    } 
} 

後でビューで、あなたが変更を反映するために使用されているUIコントロールにMyControllerからプロパティをバインドします。

データバインディングhereを参照してください。

「コントローラー/アダプターは実際に静的なクラスです」と言ったときは明確ではありませんが、上記のことが本当に役立つと思います。

もう1つのオプションはもちろんReactiveUIですが、この方法ではRx.Netとプログラミングについて反応的な方法で学ぶ必要があります。

関連する問題