MVVM模式下实现拖拽
在文章开始之前先看一看效果图
我们可以拖拽一个"游戏"给ListBox,并且ListBox也能接受拖拽过来的数据, 但是我们不能拖拽一个"游戏类型"给它。
所以当拖拽开始发生的时候我们必须添加一些限制条件,以防止接受不正确的数据。
Item实体
CS
1
2
3
4
|
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 Methods
- private 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;
- #endregion
- DragEnterCommand = 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 Commands
- public ICommand DragEnterCommand { get; set; }
- public ICommand DropCommand { get; set; }
- #endregion
- }

到这里一个简单的拖拽就完成了。
原地址:http://www.cnblogs.com/ShenNan/p/4275494.html
MVVM模式下实现拖拽的更多相关文章
- MVVM模式下弹出窗体
原地址:http://www.cnblogs.com/yk250/p/5773425.html 在mvvm模式下弹出窗体,有使用接口模式传入参数new一个对象的,还有的是继承于一个window,然后在 ...
- Silverlight中在MVVM模式下对DatagridRow选择控件封装
在项目中,凡是涉及到表格的地方用的最多的控件,自然少不了DataGrid的身影,它明了的展示各种数据让人十分喜欢.现在要实现一个功能,使DataGrid具有全选和项选中的功能,如果在传统后台代码中完成 ...
- js架构设计模式——MVVM模式下,ViewModel和View,Model有什么区别
MVVM模式下,ViewModel和View,Model有什么区别 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就 ...
- MVVM模式下 DataTemplate 中控件的绑定
今天给ListBox中通过DataTemplate生成的Button绑定命令时,一开始Button始终找不到绑定的命令.现找到了正确的绑定方式,特来记录一下. 先上个正确的示例: <ListBo ...
- WPF中在MVVM模式下,后台绑定ListCollectionView事件触发问题
问题:WPF中MVVM模式下 ListView绑定ListCollectionView时,CurrentChanged无法触发 解决方案: 初期方案:利用ListView的SelectionChang ...
- WPF实战案例-MVVM模式下在Xaml中弹出窗体
相信很多学习和开发wpf项目的同学都了解过mvvm模式,同样,在mvvm模式下会有一个不可忽视的问题,就是怎么在xaml中弹出窗体,而不破坏MVVM本身的结构. 关于弹出窗体的方式还是很多的,本文先讲 ...
- 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果
学习笔记---Javascript事件Event.IE浏览器下的拖拽效果 1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...
- WPF MVVM模式下ComboBox级联效果 选择第一项
MVVM模式下做的省市区的级联效果.通过改变ComboBox执行命令改变市,区. 解决主要问题就是默认选中第一项 1.首先要定义一个属性,继承自INotifyPropertyChanged接口.我这里 ...
- MVVM模式下 修改 store的ajax请求url。
MVVM模式下 修改 store的ajax请求url. view.down('Pro').getViewModel().getStore('xx_store').proxy.url = "s ...
随机推荐
- MAC OS X 常用通用快捷键
注:由于使用的是Windows键盘,习惯了Ctrl + c/v复制粘贴,所以修改了修饰键,Command(⌘)键和Control(^)键互换,以下的Ctrl键均为Command键,对应键盘上的实际左C ...
- code vs1506传话(塔尖)+tarjan图文详解
1506 传话 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题解 题目描述 Description 一个朋友网络,如果a认识b,那么如果a第一次收到 ...
- 将xml文件作为一个小的数据库,进行学生的增删改查
1.xml文件: <?xml version="1.0" encoding="UTF-8"?><Students> <studen ...
- OSG快速生成一个带有纹理的四边形Geometry
可以使用Geometry头文件中的 Geometry* createTexturedQuadGeometry osg::ref_ptr<osg::Texture2D> texture = ...
- IIS 发布mvc 403.14
转载: iis7 发布mvc3 遇到的HTTP错误 403.14-Forbidden Web 服务器被配置为不列出此目录的内容及Login on failed for “IIS APPPOOL\ASP ...
- cocospod 安装和使用 podfile 问题解决
Podfile 不识别 usr_framework!,系本地Pods版本太低,要在0.36以上. 以下转自:http://blog.csdn.net/eqera/article/details/393 ...
- #import、#include、#import<>和#import””的区别
一.#import与#include #import不会引起交叉编译的问题.因为在Objective-C中会存在C/C++和Object-C混编的问题,如果用#include引入头文件,会导致交叉编译 ...
- 优化MyBatis配置文件中的配置
一.为实体类定义别名,简化sql映射xml文件中的引用 之前,我们在sql映射xml文件中的引用实体类时,需要写上实体类的全类名(包名+类名),如下: <!-- 创建用户(Create) --& ...
- 解决passwd 为普通用户设密码 不成功的方法
echo "xxxxxxxxx"|passwd --stdin user_name #这样设置密码就可以成功!
- MySQL 主从同步
http://blog.csdn.net/z69183787/article/details/53897894