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 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

    }

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

QQ 3045568793 欢迎交流 , 我叫山鸡 鸡巴的鸡

你可能感兴趣的:(模式)