MVVM模式下实现拖拽

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

MVVM模式下实现拖拽

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

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

Item实体

CS

1
2
3
4
public class ItemModel : ViewModelBase
{
    public string ItemName { get; set; }
}

组实体

CS

MVVM模式下实现拖拽
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; }
}
MVVM模式下实现拖拽

给"游戏"实体创建一个模板

XAML

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

给"游戏组"实体创建一个模板

XAML

MVVM模式下实现拖拽
<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>
MVVM模式下实现拖拽

但是当我准备给TreeView赋值的时候 , 我想起来TreeView的SelectedItem属性不是依赖属性 , 它不支持Binding操作

所以只有自己写一个控件继承TreeView了。为它扩展一个MySelectedItem属性出来。并且重写SelectedItemChange事件

把TreeView的SelectedItem交给扩展的依赖属性MySelectedItem .这样在界面上就可以Binding选中项了

不过由于TreeView各个节点的数据实体可能类型不相同,所以扩展的属性只能定义为object类型

创建自定义树

CS

MVVM模式下实现拖拽
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);
}
}
MVVM模式下实现拖拽

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

MVVM模式下实现拖拽
        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);
}
}
MVVM模式下实现拖拽

DragDrop.DoDragDrop方法需要传入一个DependencyObject对象以设置其拖拽时的效果。

但由于TreeView做了数据绑定, 所以它的SelectItem取出来是一个数据实体。而不是一个DependencyObject对象了。

所以我用了一个比较SB的办法就是new一个TreeViewItem。然后设置拖拽移动的效果。

创建ListBox

MVVM模式下实现拖拽
           <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>
MVVM模式下实现拖拽

ViewModel

MVVM模式下实现拖拽
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
}
MVVM模式下实现拖拽

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

原地址:http://www.cnblogs.com/ShenNan/p/4275494.html

上一篇:js如何完整的显示较长的数字


下一篇:Mac python3.6 安装即使用 psycopg2