2009-04-24 4 views
1

私は最近、作成しているユーザーコントロールにいくつかのドラッグ/ドロップ機能を追加しました。その後のテストなどのためにドラッグ/ドロップの詳細を考慮することが理にかなっていました。コアロジックはDragOnMouseMove<TInput>()です。これは、ドラッグドロップロジックをコントロールから除外する良い方法ですか?

(フォーマットは簡潔にするためトリミング)

internal class DragState 
{ 
    private static readonly Size deadZoneSize = SystemInformation.DragSize; 
    private Rectangle dragDeadZone = Rectangle.Empty; 
    private Control owningControl = null; 

    public BlockTypeDragState(Control owner) 
    { 
     // null check boilerplate here 
     this.owningControl = owner; 
     return; 
    } 

    private bool IsActive 
    { 
     get { return this.dragDeadZone != Rectangle.Empty; } 
    } 

    public void DragOnMouseMove(
     Point mouseAt, 
     DragDropEffects allowedEffects, 
     Func<object> generateDragData) 
    { 
     this.DragOnMouseMove<object>(
      mouseAt, 
      allowedEffects, 
      null, 
      s => generateDragData()); 
     return; 
    } 

    public void DragOnMouseMove<TInput>(
     Point mouseAt, 
     DragDropEffects allowedEffects, 
     TInput generateParm, 
     Func<TInput, object> generateDragData) 
    { 
     // boilerplate null check on generateDragData 
     if (this.DragShouldStart(mouseAt)) 
     { 
      object data = generateDragData(generateParm); 
      this.owningControl.DoDragDrop(data, allowedEffects); 

      this.Reset(); 
     } 
     return; 
    } 

    public void ListenForDrag(int x, int y) 
    { 
     this.dragDeadZone = new Rectangle(new Point(x - (deadZoneSize.Width/2), y - (deadZoneSize.Height/2)), deadZoneSize); 
     return; 
    } 

    public void Reset() { this.dragDeadZone = Rectangle.Empty; } 

    private bool DragShouldStart(Point mouseClientLocation) 
    { 
     if (this.IsActive && !this.dragDeadZone.Contains(mouseClientLocation)) 
     { return true; } 
     return false; 
    } 
} 

使用法は、その後のようになります。ここにコメントが正である場合、私は(まだそれを一般化していないと私は何かを必要とすることを考えると

private DragState dragState = new DragState(this); // pseudo 

// MouseMove event handler 
private void HandleMouseMove(object sender, MouseEventArgs e) 
{ 
    // Perform the drag/drop. 
    this.dragState.DragOnMouseMove(
     new Point(e.X, e.Y), 
     DragDropEffects.Copy, 
     () => this.BuildDataToDragDrop()); 

    return; 
} 

private void HandleMouseDown(object sender, MouseEventArgs e) 
{ 
    if (this.CanDragDrop(sender, e)) this.dragState.ListenForDrag(e.X, e.Y); 
} 

private void HandleMouseUp(object sender, MouseEventargs e) 
{ 
    this.dragState.Reset(); 
} 

2回目のように、私はおそらく)、これは生産コードのために合理的です、または私はComplicatorですか?あなたが保守していたコードでこれを見たなら、あなたは私を厄介な名前と呼ぶでしょうか? :)

すべてのコメントは、名前の提案を含めて大歓迎です。 (DragStateが好きではありません)

例えば、これは良いアイデアだとしたら、parmsで拡張性ポイントを機能させるのがより意味があるかどうかはまだ分かりません(Func<>そしてOnGenerateData<TInput>(TInput parm)OnDropCompleted(DragDropEffects result)などの必須のオーバーライドを持つ抽象DragStateBase経由Action<>それが今であるように)またはOO()

答えて

0

いくつかのポイント:

0制御がDragStateについてはあまり詳細を知っています。私には、DragStateにMouseDown()、MouseUpなどのメソッドを作成する方が良いです。

1ドラッグをキャンセルする必要がある場合はどうなりますか?

2 DoDragDropをクラスDragStateで使用するのはなぜですか?

private void HandleMouseDown(object sender, MouseEventArgs e) { dragState.MouseMove(new Point(e.X,e.Y), (d,e) => DoDragDrop(d,e)); }

3クラスがDragControllerになるこの方法ではなく、状態をドラッグします。

4ドラッグドロップのロジックがたくさん必要な場合は、コントローラにステートマシンを導入しようとすることができます。

5選択矩形を実装する必要がある場合はどうなりますか?あなたはドラッグドロップのための真のコントローラーをほぼ実装しましたが、それは非常に有用ではないようです。

6 ListenForDragは実際に何も聞きません。開始点を設定するだけです:-)

7 dragDeadZoneはいい名前です。私の目的にそれを使用します

8追加のロジックが必要な場合は、たとえばselect-drag-showコンテキストメニューを使用しますか?あなたはDragControllerではなく、InpurControllerを使っています。こうすることで、入力に関連するすべてのロジックをコントロールクラス外に移動して再利用することができます。

関連する問題