2009-06-23 37 views
6

我試圖在使用MVVM模式構建的Surface應用程序中實現拖放功能。我正努力想出一個方法來實現這一點,同時堅持MVVM模式。雖然我試圖在Surface應用程序中執行此操作,但我認爲該解決方案也足以應用於WPF。使用ScatterView在MVVM中拖放

我試圖產生以下功能:

  • 用戶接觸ScatterViewItem內的FrameworkElement的開始的拖動操作(ScatterViewItem的特定部分啓動拖/放功能)
  • 當拖動操作開始創建該ScatterViewItem的副本並將其強加到原始ScatterViewItem上,副本是用戶將拖動並最終丟棄的內容
  • 用戶可以將該項目拖放到另一個ScatterViewItem(放置在單獨的ScatterView中)

除了源對象包含在ScatterView而不是ListBox中之外,整體交互非常類似於Surface SDK中提供的ShoppingCart應用程序。

我不確定如何繼續以便啓用ViewModel之間的正確通信以提供此功能。我遇到的主要問題是在用戶聯繫FrameworkElement時複製ScatterViewItem。

+0

有沒有機會看到一些代碼? ScatterViewItems如何持有兒童控件?你如何將它綁定到視圖模型? – 2009-06-25 19:34:33

回答

4

您可以使用附加屬性。創建一個附加屬性,並在setProperty方法綁定到DROP掉事件:


public static void SetDropCommand(ListView source, ICommand command) 
     { 
      source.Drop += (sender, args) => 
           { 
            var data = args.Data.GetData("FileDrop"); 
            command.Execute(data); 
           }; 
     } 

然後你就可以在你的視圖模型綁定命令在視圖中的相關控制。顯然,你可能想讓你的附加屬性適用於你的特定控件類型,而不是一個列表視圖。

希望有所幫助。

2

我有一個讓史蒂夫帕瑟利斯的想法工作。這花了一段時間 - 自定義依賴屬性很容易出錯。它看起來像SetXXX是錯誤的地方放你的副作用 - WPF不必去那​​裏,它可以直接去DependencyObject.SetValue,但總是會調用PropertyChangedCallback

所以,這裏的完整和工作自定義附加屬性代碼:

using System.Windows; 
using System.Windows.Input; 

namespace WpfApplication1 
{ 
    public static class PropertyHelper 
    { 
     public static readonly DependencyProperty DropCommandProperty = DependencyProperty.RegisterAttached(
      "DropCommand", 
      typeof(ICommand), 
      typeof(PropertyHelper), 
      new PropertyMetadata(null, OnDropCommandChange)); 

     public static void SetDropCommand(DependencyObject source, ICommand value) 
     { 
      source.SetValue(DropCommandProperty, value); 
     } 

     public static ICommand GetDropCommand(DependencyObject source) 
     { 
      return (ICommand)source.GetValue(DropCommandProperty); 
     } 

     private static void OnDropCommandChange(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      ICommand command = e.NewValue as ICommand; 
      UIElement uiElement = d as UIElement; 
      if (command != null && uiElement != null) 
      { 
       uiElement.Drop += (sender, args) => command.Execute(args.Data); 
      } 

      // todo: if e.OldValue is not null, detatch the handler that references it 
     } 
    } 
} 

在要使用此XAML標記,你可以做如

xmlns:local="clr-namespace:WpfApplication1" 
... 
<Button Content="Drop here" Padding="12" AllowDrop="True" 
    local:PropertyHelper.DropCommand="{Binding DropCommand}" /> 

..其餘的只是確保你的ViewModel,綁定和命令是正確的。

該版本將IDataObject傳遞給我看起來更好的命令 - 您可以查詢它的文件或命令中的任何內容。但這只是當前的偏好,而不是答案的基本特徵。