2009-12-07 42 views

回答

1

在用戶控制

實現具有參數的命令。我使用ICommand與Josh Smiths RelayCommand,但我擴展它給它一個參數。 (代碼在這個答案的結尾)

/// <summary> 
    /// Gets and Sets the ICommand that manages dragging and dropping. 
    /// </summary> 
    /// <remarks>The CanExecute will be called to determin if a drop can take place, the Executed is called when a drop takes place</remarks> 
    public ICommand DragDropCommand { 
    get { return (ICommand)GetValue(DragDropCommandProperty); } 
    set { SetValue(DragDropCommandProperty, value); } 

現在你可以綁定你的視圖模型到這個命令。

設置另一個屬性爲我們的實體阻力型(你可以硬編碼此),但我重複使用不同的東西,這個用戶控件,我不想一個控制接受上下降了錯誤的實體類型。

/// <summary> 
    /// Gets and Sets the Name of the items we are dragging 
    /// </summary> 
    public String DragEntityType { 
    get { return (String)GetValue(DragEntityTypeProperty); } 
    set { SetValue(DragEntityTypeProperty, value); } 
    } 

覆蓋的OnPreviewLeftMouseButtonDown

protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) { 
     //find the item the mouse is over, i.e. the one you want to drag. 
     var itemToDrag = FindItem(e); 

     //move the selected items, using the drag entity type 
     DataObject data = new DataObject(this.DragEntityType, itemToDrag); 
     //use the helper class to initiate the drag 
     DragDropEffects de = DragDrop.DoDragDrop(this, data, DragDropEffects.Move); 

     //call the base 
     base.OnPreviewMouseLeftButtonDown(e); 
    } 

當你調用DragDrop.DoDragDrop,下面的方法將在選擇恰當的時間

覆蓋的OnDragOver和OnDragDrop方法調用,並使用命令問我們是否可以拖動,我們可以下降

protected override void OnDragOver(DragEventArgs e) { 

    //if we can accept the drop 
    if (this.DragDropCommand != null && this.DragDropCommand.CanExecute(e.Data)) { 

     // Console.WriteLine(true); 
    } 
    //otherwise 
    else { 
     e.Effects = DragDropEffects.None; 
     e.Handled = true; 
    } 
    base.OnDragOver(e); 
    } 

    protected override void OnDrop(DragEventArgs e) { 

    if (this.DragDropCommand == null) { } 
    //if we dont allow dropping on ourselves and we are trying to do it 
    //else if (this.AllowSelfDrop == false && e.Source == this) { } 
    else { 
     this.DragDropCommand.Execute(e.Data); 
    } 
    base.OnDrop(e); 
    } 

在視圖模型

那麼當你在視圖模型使用像這樣設置你的命令,然後將命令綁定到用戶控件

 this.MyDropCommand = new ExtendedRelayCommand((Object o) => AddItem(o), (Object o) => { return ItemCanBeDragged(o); }); 

通常你是從一個用戶拖動控制到另一個,因此您將爲一個用戶控件設置一個命令,爲另一個用戶控件設置一個命令,每個命令都具有您將接受的不同DragEntityType。兩個用戶控制一個拖動,一個拖放,並且反之亦然。每個用戶控件都有不同的DragEntityType,因此您可以知道拖動源自哪一個。

private Boolean ItemCanBeDragged(object o) { 
    Boolean returnValue = false; 

    //do they have permissions to dragt 
    if (this.HasPermissionToDrag) { 

     IDataObject data = o as IDataObject; 

     if (data == null) { } 
     //this line looks up the DragEntityType 
     else if (data.GetDataPresent("ItemDragEntityTypeForItemWeAreDragging")) { 
      returnValue = true; 
     } 
    } 
    return returnValue; 
    } 

,當我們放棄

private void AddItem(object o) { 
    IDataObject data = o as IDataObject; 

    if (data == null) { } 
    else { 
     MyDataObject myData = data.GetData("ItemDragEntityTypeForItemWeAreDroppingHere") as MyDataObject ; 

     if (myData == null) { } 
     else { 
      //do something with the dropped data 
     } 
    } 
    } 

我可能錯過了一些東西,但這種技術可以讓我向視圖模型,如果我可以拖動一個項目,讓我問視圖模型,如果我能拖放(如果視圖模型將接受該項目)其可綁定,並且它很好地分離視圖/視圖模型。如果你有任何問題隨時問。

擴展接力指揮,感謝約什 - 史密斯......

/// <summary> 
    /// A command whose sole purpose is to 
    /// relay its ExtendedFunctionality to other 
    /// objects by invoking delegates. The 
    /// default return value for the CanExecute 
    /// method is 'true'. 
    /// </summary> 
    public class ExtendedRelayCommand : ICommand { 
     #region Constructors 

     /// <summary> 
     /// Creates a new command that can always execute. 
     /// </summary> 
     /// <param name="execute">The execution logic.</param> 
     public ExtendedRelayCommand(Action<Object> execute) 
     : this(execute, null) { 
     } 

     /// <summary> 
     /// Creates a new command. 
     /// </summary> 
     /// <param name="execute">The execution logic.</param> 
     /// <param name="canExecute">The execution status logic.</param> 
     public ExtendedRelayCommand(Action<Object> execute, Func<Object, bool> canExecute) { 
     if (execute == null) 
      throw new ArgumentNullException("execute"); 

     _execute = execute; 
     _canExecute = canExecute; 
     } 

     #endregion // Constructors 

     #region ICommand Members 

     [DebuggerStepThrough] 
     public bool CanExecute(object parameter) { 
     return _canExecute == null ? true : _canExecute(parameter); 
     } 

     public event EventHandler CanExecuteChanged { 
     add { 
      if (_canExecute != null) 
       CommandManager.RequerySuggested += value; 
     } 
     remove { 
      if (_canExecute != null) 
       CommandManager.RequerySuggested -= value; 
     } 
     } 

     public void Execute(object parameter) { 
     _execute(parameter); 
     } 

     #endregion // ICommand Members 

     #region Fields 

     readonly Action<Object> _execute; 
     readonly Func<Object, bool> _canExecute; 

     #endregion // Fields 
    }