MVVM模式下實現拖拽

MVVM模式下實現拖拽
原文:MVVM模式下實現拖拽

在文章開始之前先看一看效果圖

我們可以拖拽一個"游戲"給ListBox,并且ListBox也能接受拖拽過來的數據, 但是我們不能拖拽一個"游戲類型"給它。

所以當拖拽開始發生的時候我們必須添加一些限制條件,以防止接受不正確的數據。

?

?

Item實體

CS

    public class ItemModel : ViewModelBase{public string ItemName { get; set; }}

?

組實體

CS

public class GroupModel : ViewModelBase{/// <summary>/// 組名/// </summary>public string GroupName { get; set; }private int groupCount;/// <summary>/// 組數量/// </summary>public int GroupCount{get { return groupCount; }set { groupCount = value; base.RaisePropertyChanged("GroupCount"); }}/// <summary>/// 子類集合/// </summary>public ObservableCollection<ItemModel> ItemModelList { get; set; }}

?

給"游戲"實體創建一個模板

XAML

<HierarchicalDataTemplate x:Key="template_Item"><TextBlock Text="{Binding ItemName}"/>
</HierarchicalDataTemplate>

?

給"游戲組"實體創建一個模板

XAML

<HierarchicalDataTemplate x:Key="template_Group" ItemsSource="{Binding ItemModelList}" ItemTemplate="{StaticResource template_Item}"><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding GroupName}"/><TextBlock Text="{Binding GroupCount}" Margin="5,0,0,0"/></StackPanel>
</HierarchicalDataTemplate>

?

但是當我準備給TreeView賦值的時候 , 我想起來TreeView的SelectedItem屬性不是依賴屬性 , 它不支持Binding操作

所以只有自己寫一個控件繼承TreeView了。為它擴展一個MySelectedItem屬性出來。并且重寫SelectedItemChange事件

把TreeView的SelectedItem交給擴展的依賴屬性MySelectedItem .這樣在界面上就可以Binding選中項了

不過由于TreeView各個節點的數據實體可能類型不相同,所以擴展的屬性只能定義為object類型

?

創建自定義樹

CS

public class MyTreeView : TreeView{public MyTreeView(){}/// <summary>/// 自定義TreeView選中項,支持數據Binding/// </summary>public object MySelectItem{get { return GetValue(MySelectItemProperty); }set { SetValue(MySelectItemProperty, value); }}public static DependencyProperty MySelectItemProperty = DependencyProperty.Register("MySelectItem", typeof(object), typeof(MyTreeView));/// <summary>/// 當改變發生時,為自定義的SelectItem屬性賦值/// </summary>/// <param name="e"></param>protected override void OnSelectedItemChanged(RoutedPropertyChangedEventArgs<object> e){if (this.SelectedItem != null)this.MySelectItem = this.SelectedItem;base.OnSelectedItemChanged(e);}}

XAML

 <mc:MyTreeView x:Name="myTree" MouseMove="TreeView_MouseMove" TextBlock.FontSize="14" MySelectItem="{Binding SelectGame,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding GroupSourceList}" ItemTemplate="{StaticResource template_Group}">
</mc:MyTreeView>

?

CS

        private TreeViewItem ti = new TreeViewItem();private void TreeView_MouseMove(object sender, MouseEventArgs e){if (e.LeftButton == MouseButtonState.Pressed){if (myTree.SelectedItem == null)return;DragDrop.DoDragDrop(ti, sender, DragDropEffects.Move);}}

DragDrop.DoDragDrop方法需要傳入一個DependencyObject對象以設置其拖拽時的效果。

但由于TreeView做了數據綁定, 所以它的SelectItem取出來是一個數據實體。而不是一個DependencyObject對象了。

所以我用了一個比較SB的辦法就是new一個TreeViewItem。然后設置拖拽移動的效果。

?

創建ListBox

           <ListBox ItemsSource="{Binding GameSourceList}" AllowDrop="true"><ListBox.ItemTemplate><DataTemplate><TextBlock Text="{Binding ItemName}"/></DataTemplate></ListBox.ItemTemplate><i:Interaction.Triggers><i:EventTrigger EventName="DragEnter"><Command:EventToCommand Command="{Binding DragEnterCommand}" PassEventArgsToCommand="True"/></i:EventTrigger><i:EventTrigger EventName="DragOver"><Command:EventToCommand Command="{Binding DragEnterCommand}" PassEventArgsToCommand="True"/></i:EventTrigger><i:EventTrigger EventName="Drop"><Command:EventToCommand Command="{Binding DropCommand}" PassEventArgsToCommand="True"/></i:EventTrigger></i:Interaction.Triggers></ListBox>

ViewModel?

public class MainViewModel : ViewModelBase{public MainViewModel(){Init();}#region Properties/// <summary>/// 數據源/// </summary>public ObservableCollection<GroupModel> GroupSourceList { get; set; }/// <summary>/// 數據源/// </summary>public ObservableCollection<ItemModel> GameSourceList { get; set; }private object selectGame;/// <summary>/// 當前選中項/// </summary>public object SelectGame{get { return selectGame; }set{selectGame = value;base.RaisePropertyChanged("SelectGame");}}#endregion#region Methodsprivate void Init(){GameSourceList = new ObservableCollection<ItemModel>();GroupSourceList = new ObservableCollection<GroupModel>();GroupModel gp1 = new GroupModel();#region 模擬數據gp1.GroupName = "競技游戲";gp1.ItemModelList = new ObservableCollection<ItemModel>();gp1.ItemModelList.Add(new ItemModel() { ItemName = "CS GO" });gp1.ItemModelList.Add(new ItemModel() { ItemName = "星際爭霸2" });gp1.ItemModelList.Add(new ItemModel() { ItemName = "FIFA 14" });gp1.GroupCount = gp1.ItemModelList.Count;GroupModel gp2 = new GroupModel();gp2.GroupName = "網絡游戲";gp2.ItemModelList = new ObservableCollection<ItemModel>();gp2.ItemModelList.Add(new ItemModel() { ItemName = "CS OnLine" });gp2.ItemModelList.Add(new ItemModel() { ItemName = "街頭籃球" });gp2.ItemModelList.Add(new ItemModel() { ItemName = "完美世界" });gp2.GroupCount = gp2.ItemModelList.Count;GroupModel gp3 = new GroupModel();gp3.GroupName = "休閑游戲";gp3.ItemModelList = new ObservableCollection<ItemModel>();gp3.ItemModelList.Add(new ItemModel() { ItemName = "德州撲克" });gp3.ItemModelList.Add(new ItemModel() { ItemName = "街頭籃球" });gp3.ItemModelList.Add(new ItemModel() { ItemName = "完美世界" });GroupSourceList.Add(gp1);GroupSourceList.Add(gp2);GroupSourceList.Add(gp3);gp3.GroupCount = gp3.ItemModelList.Count;#endregionDragEnterCommand = new RelayCommand<DragEventArgs>(DragEnter);DropCommand = new RelayCommand<DragEventArgs>(Drop);}private void DragEnter(DragEventArgs args){if (SelectGame.GetType() == typeof(ItemModel)) //如果拖拽的對象是"游戲"則接受之
            {args.Effects = DragDropEffects.Move;System.Console.WriteLine("accept");}else{args.Effects = DragDropEffects.None;       //否則拒絕接受拖拽System.Console.WriteLine("no accept");}args.Handled = true;}private void Drop(DragEventArgs args){GameSourceList.Add(SelectGame as ItemModel);   //將接受到的"游戲"寫入ListBox
        }#endregion#region Commandspublic ICommand DragEnterCommand { get; set; }public ICommand DropCommand { get; set; }#endregion}

到這里一個簡單的拖拽就完成了。

QQ?3045568793 歡迎交流?

posted on 2019-03-15 13:18 NET未來之路 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/lonelyxmas/p/10536423.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/249446.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249446.shtml
英文地址,請注明出處:http://en.pswp.cn/news/249446.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

nodejs變量

https://www.cnblogs.com/vipyoumay/p/5597992.html

jenkins+Docker持續化部署(筆記)

參考資料&#xff1a;https://www.cnblogs.com/leolztang/p/6934694.html &#xff08;Jenkins&#xff08;Docker容器內&#xff09;使用宿主機的docker命令&#xff09; https://container-solutions.com/running-docker-in-jenkins-in-docker/ &#xff08;Running Docker i…

正則表達式之括號

正則表達式&#xff08;三&#xff09; 括號 分組 量詞可以作用字符或者字符組后面作為限定出現次數&#xff0c;如果是限制多個字符出現次數或者限制一個表達式出現次數&#xff0c;需要使用括號()將多個字符或者表達式括起來&#xff0c;這樣便稱為分組。例如(ab)表示“ab”字…

免安裝Mysql在Mac中的神坑之Access denied for user 'root'@'localhost' (using password: YES)

眼看馬上夜深人靜了&#xff0c;研究了一天的問題也塵埃落定了。 廢話不多說 直接來干貨&#xff01; 大家都知道免安裝版本的Mysql, 在Mac中安裝完成&#xff08;如何安裝詳見Mac OS X 下 TAR.GZ 方式安裝 MySQL&#xff09;之后&#xff0c;在登錄時會遇到沒有訪問權限的問題…

nodejs函數

https://www.cnblogs.com/yourstars/p/6121262.html

[HNOI2009]夢幻布丁

題目描述 N個布丁擺成一行,進行M次操作.每次將某個顏色的布丁全部變成另一種顏色的,然后再詢問當前一共有多少段顏色.例如顏色分別為1,2,2,1的四個布丁一共有3段顏色. 第一行給出N,M表示布丁的個數和好友的操作次數. 第二行N個數A1,A2...An表示第i個布丁的顏色從第三行起有M行,…

用jquery實現html5的placeholder功能

版權聲明&#xff1a;本文為博主原創文章。未經博主同意不得轉載。 https://blog.csdn.net/QianShouYuZhiBo/article/details/28913501 html5的placeholder功能在表單中經經常使用到。它主要用來提示用戶輸入信息&#xff0c;當用戶點擊該輸入框之后&#xff0c;提示文字會自己…

mac環境下node.js和phonegap/cordova創建ios和android應用

mac環境下node.js和phonegap/cordova創建ios和android應用 一介布衣 2015-01-12 nodejs 6888 分享到&#xff1a;QQ空間新浪微博騰訊微博人人網微信引用百度百科的一段描述:PhoneGap是一個用基于HTML&#xff0c;CSS和JavaScript的&#xff0c;創建移動跨平臺移動應用程序的…

java中多線程 - 多線程中的基本方法

介紹一下線程中基本的方法使用 線程睡眠sleep() Thread.sleep(毫秒);我們可以通過sleep方法設置讓線程睡眠。可以看到sleep是個靜態方法 public static native void sleep(long var0) throws InterruptedException; try {System.out.println(new Date().getSeconds());Thread.s…

nodejs匿名函數

https://www.cnblogs.com/sharpest/p/8056232.html

Deployment descriptor

Deployment descriptor 是指一種配置文件用于工件部署到一些container/engine。 在Java Platform&#xff0c;Enterprise Edition中&#xff0c;部署描述符描述了應如何部署組件&#xff0c;模塊或應用程序&#xff08;如Web應用程序或企業應用程序&#xff09;。它指示部署工具…

cordova 一個將web應用程序封裝成app的框架

cordova 一個將web應用程序封裝成app的框架 cordova的詳細介紹請參考這個鏈接&#xff1a;http://www.zhoujingen.cn/blog/7034.html 我接下來主要將如何搭建。 1.首先你需要下載幾樣東西 1.jdk. 2.android_SDK. 2.安裝這兩個&#xff0c;并配置環境變量 這里jdk的環境變量配置…

windows linux 子系統折騰記

最近買了部新電腦&#xff0c;海爾n4105的一體機&#xff0c;好像叫s7。 放在房間里面&#xff0c;看看資料。因為性能孱弱&#xff0c;所以不敢安裝太強大的軟件&#xff0c;然后又有一顆折騰的心。所以嘗試了win10自帶的linux子系統。然后在應用商店搜索linux推薦debian 系統…

nodejs閉包

一、什么是閉包&#xff1f; 官方”的解釋是&#xff1a;閉包是一個擁有許多變量和綁定了這些變量的環境的表達式&#xff08;通常是一個函數&#xff09;&#xff0c;因而這些變量也是該表達式的一部分。 相信很少有人能直接看懂這句話&#xff0c;因為他描述的太學術。其實這…

《深入理解Java虛擬機》讀書筆記八

第九章 類加載及執行子系統的案例與實戰 Q&#xff1a;如果有10個WEB應用程序都是用Spring來進行組織管理的話&#xff0c;可以把Spring放到Common或Shared目錄下&#xff08;Tomcat5.0&#xff09;讓這些程序共享。Spring要對用戶程序的類進行管理&#xff0c;自然要能訪問到用…

一些非常有用的鏈接和工具

微信公眾平臺SDK Senparc.Weixin for C#&#xff0c;支持.NET Framework及.NET Core &#xff1a; https://github.com/JeffreySu/WeiXinMPSDK layui開發文檔地址&#xff1a;https://www.layui.com/doc/ .Net Core GitHub社區 &#xff1a; https://github.com/dotnetcore EF…

Activity Intent相關FLAG介紹

先首先簡單介紹下Task和Activity的關系 Task就像一個容器&#xff0c;而Activity就相當與填充這個容器的東西&#xff0c;第一個東西&#xff08;Activity&#xff09;則會處于最下面&#xff0c;最后添加的東西&#xff08;Activity&#xff09;則會在最上面。從Task中取出東西…

js的原型和原型鏈

構造函數創建對象&#xff1a; function Person() {} var person new Person(); person.name Kevin; console.log(person.name) // KevinPerson 就是一個構造函數&#xff0c;我們使用 new 創建了一個實例對象 person prototype 每個函數都有一個 prototype 屬性 每一個Ja…

二維數組

要求&#xff1a;求一個二維數組的最大子數組和 思路&#xff1a;對于這個題&#xff0c;我會最簡單的讀取&#xff0c;雖然在網上查到了代碼&#xff0c;但是查找最大子數組的循環我真的看不懂&#xff0c;也不是特別懂思路&#xff0c;所以在這不會寫思路 package 二維數組; …

資源

資源鏈接&#xff1a; 內存池TinySTLminiSTLcghSTL1. lishuhuakai 2. 轉載于:https://www.cnblogs.com/sunbines/p/9707483.html