2009-12-07 43 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 
    }