MVVM模式下实现拖拽

摘要:
项实体CSpublicclassItemModel:ViewModelBase{publicstringItemName{get;set;}}组实体CSpublicclassGroupModel:ViewModelBase{//////组名称//publicstringGroupName{get;set;}私有组计数;//////组数////publicantGroupCount{get{returngroupCount;}set{groupCount=value;base.RaisePropertyChanged;}}//////子类集合////publicObservableCollectionItemModelList{get;set;}}为“游戏”实体XAML创建模板{BindingGroupName}“/˃˂/HierarchicalDataTemplate=null)this.MySelectItem=this.SelectedItem;base.OnSelectedItemChanged;}}XAMLCSprivateTreeViewItemti=newTreeViewName();privatevoidTreeView_MouseMove{if{ifreturn;DragDrop.DoDragDrop;}}DragDrop。DoDragDrop方法需要传入DependencyObject对象来设置其拖动效果。

在文章开始之前先看一看效果图

MVVM模式下实现拖拽第1张

我们可以拖拽一个"游戏"给ListBox,并且ListBox也能接受拖拽过来的数据, 但是我们不能拖拽一个"游戏类型"给它。

所以当拖拽开始发生的时候我们必须添加一些限制条件,以防止接受不正确的数据。

Item实体

CS

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

组实体

CS

public classGroupModel : ViewModelBase
    {
        /// <summary>
        ///组名
        /// </summary>
        public string GroupName { get; set; }
        private intgroupCount;
        /// <summary>
        ///组数量
        /// </summary>
        public intGroupCount
        {
            get { returngroupCount; }
            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 classMyTreeView : TreeView
    {
        publicMyTreeView()
        {
        }
        /// <summary>
        ///自定义TreeView选中项,支持数据Binding
        /// </summary>
        public objectMySelectItem
        {
            get { returnGetValue(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 = newTreeViewItem();
        private void TreeView_MouseMove(objectsender, 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 classMainViewModel : ViewModelBase
    {
        publicMainViewModel()
        {
            Init();
        }
        #region Properties
        /// <summary>
        ///数据源
        /// </summary>
        public ObservableCollection<GroupModel> GroupSourceList { get; set; }
        /// <summary>
        ///数据源
        /// </summary>
        public ObservableCollection<ItemModel> GameSourceList { get; set; }
        private objectselectGame;
        /// <summary>
        ///当前选中项
        /// </summary>
        public objectSelectGame
        {
            get { returnselectGame; }
            set
            {
                selectGame =value;
                base.RaisePropertyChanged("SelectGame");
            }
        }
        #endregion
        #region Methods
        private voidInit()
        {
            GameSourceList = new ObservableCollection<ItemModel>();
            GroupSourceList = new ObservableCollection<GroupModel>();
            GroupModel gp1 = newGroupModel();
            #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 = newGroupModel();
            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 = newGroupModel();
            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 voidDragEnter(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 voidDrop(DragEventArgs args)
        {
            GameSourceList.Add(SelectGame as ItemModel);   //将接受到的"游戏"写入ListBox
}
        #endregion
        #region Commands
        public ICommand DragEnterCommand { get; set; }
        public ICommand DropCommand { get; set; }
        #endregion
    }

到这里一个简单的拖拽就完成了。

QQ3045568793 欢迎交流

免责声明:文章转载自《MVVM模式下实现拖拽》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇(原)调用jpeglib对图像进行压缩CLR寄宿(上) MSCOREE.DLL下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

DevExpress WinForm MVVM数据和属性绑定指南(Part 1)

根据您绑定的属性,存在以下三种可能的情况: 常规绑定- ViewModel属性绑定到任何不可编辑的View元素属性。由于该元素不可编辑,因此您无需将更新通知发送回绑定属性(单向绑定)。 数据绑定- Model属性(数据字段)绑定到编辑器属性。如果用户可以更改编辑器值,则需要更新绑定属性(双向绑定)。 属性依赖- 来自同一个ViewModel的两个属性被绑...

C# 里TreeView绑定数据库实现分类

view plaincopy to clipboardprint? //从数据库中读取数据 SqlConnectioncon=newSqlConnection("server=127.0.0.1\\sqlexpress;uid=sa;"); con.Open(); con.ChangeDatabase("STggggg");...

MVVM(使用Prism框架)开发WPF

【MVVM】目的是为了分离视图(View)和模型(Model)的耦合——解耦 1、View负责前端展示,与ViewModel进行数据和命令的交互。(双向的数据属性传递,单向的命令属性传递View→ViewModel) 2、ViewModel,负责前端视图业务级别的逻辑结构组织,并将其反馈给前端。 3、Model,主要负责数据实体的结构处理,与ViewMod...

C# 中采用treeview递归生成目录树(Winform和Webform两种)

部门表: 课程表: 查询结果结构: 数据结构分析,部门分为部门id和部门名称;课程分为课程id,课程名称,课程路径和课程所属部门。 要求以部门为父节点展示不同部门下的课程。 Winform采用treeview递归生成目录树using System;using System.Collections.Generic;using System.Comp...

WPF中TreeView控件的使用案例

WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用。我这个demo主要是在wpf中使用TreeView控件实现图片查看功能,简单的Grid布局、TreeView控件添加图标、TreeView控件的一些事件、显示统计、还有就是读取文件操作。 效果图:...

MVC和MVVM

提到MVC,编程的人都会知道,我说的多了,就变成了啰嗦,MVC这个名词,是在大三的时候接触,但是没用过,当时我是以看书为主,很少动手,大四实习的时候,项目经理安排一个程序,让我按照MVC的方式去写,因为当时我是给已有的系统扩充功能,公司的系统有自己的框架,我只是照猫画虎,并没在意,功能实现了,就草草了事。 工作了,自己回头看以前写的代码,惨不忍睹,一个类中...