我有以下类:
public class VM_AssetPack : INotifyPropertyChanged, IHasAttributeGroupMenu, IDropTarget, IHasSubgroupViewModels
{
public ObservableCollection<VM_Subgroup> Subgroups { get; set; }
}
public class VM_Subgroup : INotifyPropertyChanged, ICloneable, IDropTarget, IHasSubgroupViewModels
{
public ObservableCollection<VM_Subgroup> RequiredSubgroups { get; set; }
public ObservableCollection<VM_Subgroup> ExcludedSubgroups { get; set; }
public ObservableCollection<VM_Subgroup> Subgroups { get; set; }
}
VM_AssetPack的子组显示在绑定到subgroups属性的树视图中。VM_Subgroup的Required/Excluded子组将在列表框中显示。这是布局的截图。这是项目的Git存储库(我还没有将最新的更改推送到拖拽&下降)。我想实现以下行为:
通过左键从树视图拖动到树视图:移动子组以降低目标的子组
通过右键从树视图拖动到树视图:复制子组以降低目标的子组
通过任何单击从树视图拖动到列表框:复制子组以降低目标的R/E子组
我目前有树视图拖放工作所需的。Xaml (UserControl_AssetPack):
<TreeView Grid.Row="5" Grid.Column="0" Name="TVsubgroups" ItemsSource ="{Binding Subgroups}" Margin="0 0 15 0" dd:DragDrop.IsDragSource="True" dd:DragDrop.IsDropTarget="True" dd:DragDrop.DropHandler="{Binding}" dd:DragDrop.CanDragWithMouseRightButton="True">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:VM_Subgroup}" ItemsSource="{Binding Subgroups}" >
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5 0 5 0" PreviewMouseLeftButtonDown="HandleSelectPreviewMouseDown" MouseLeftButtonUp="HandleSelectPreviewMouseUp">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}">
<Binding Path="Name"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding SelectedSubgroupChanged}" CommandParameter="{Binding ElementName=TVsubgroups, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TreeView>
ContentPresenter Grid.Row="5" Grid.Column="1" Content="{Binding ElementName=TVsubgroups, Path=SelectedItem}" Name="SubgroupPresenter">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:VM_Subgroup}">
<local:UC_Subgroup Background="Black" Margin="0 0 0 10"/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
View Model (VM_AssetPack):
public bool DropInitiatedRightClick { get; set; }
public void DragOver(IDropInfo dropInfo)
{
if (dropInfo.Data is VM_Subgroup)
{
dropInfo.DropTargetAdorner = DropTargetAdorners.Highlight;
dropInfo.Effects = DragDropEffects.Move;
if (dropInfo.KeyStates.HasFlag(DragDropKeyStates.RightMouseButton))
{
DropInitiatedRightClick = true;
}
}
}
public void Drop(IDropInfo dropInfo)
{
if (dropInfo.Data is VM_Subgroup && (dropInfo.TargetItem is IHasSubgroupViewModels || dropInfo.TargetItem is ObservableCollection<VM_Subgroup>))
{
var draggedSubgroup = (VM_Subgroup)dropInfo.Data;
var clone = (VM_Subgroup)draggedSubgroup.Clone();
if (dropInfo.TargetItem is VM_Subgroup)
{
VM_Subgroup dropTarget = (VM_Subgroup)dropInfo.TargetItem;
if (dropTarget.Name == draggedSubgroup.Name && dropTarget.ID == draggedSubgroup.ID) { return; }
clone.ParentCollection = dropTarget.Subgroups;
clone.ParentAssetPack = dropTarget.ParentAssetPack;
dropTarget.Subgroups.Add(clone);
}
else if (dropInfo.TargetItem is VM_AssetPack)
{
VM_AssetPack dropTarget = (VM_AssetPack)dropInfo.TargetItem;
clone.ParentCollection = dropTarget.Subgroups;
clone.ParentAssetPack = dropTarget;
dropTarget.Subgroups.Add(clone);
}
if (!DropInitiatedRightClick)
{
draggedSubgroup.ParentCollection.Remove(draggedSubgroup);
}
}
DropInitiatedRightClick = false;
}
这允许我在如上所述的树视图中拖放(尽管它不允许我将嵌套的内部子组叶子拖到树视图的顶层,或者重新安排节点上叶子的顺序-如果有人能帮助我启用这个,我会很感激)。我遇到的主要问题是列表框:
Xaml (UserControl_Subgroup):
<ListBox Grid.Row="15" Grid.Column="1" ItemsSource="{Binding RequiredSubgroups}" IsSynchronizedWithCurrentItem="True" dd:DragDrop.IsDropTarget="True" dd:DragDrop.DropHandler="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}:{1}">
<Binding Path="ID" />
<Binding Path="Name" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Grid.Row="16" Grid.Column="1" ItemsSource="{Binding ExcludedSubgroups}" IsSynchronizedWithCurrentItem="True" dd:DragDrop.IsDropTarget="True" dd:DragDrop.DragDropCopyKeyState="None">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}:{1}">
<Binding Path="ID" />
<Binding Path="Name" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
View Model (VM_Subgroup):
public object Clone()
{
return this.MemberwiseClone();
}
public void DragOver(IDropInfo dropInfo)
{
if (dropInfo.Data is VM_Subgroup)
{
dropInfo.DropTargetAdorner = DropTargetAdorners.Highlight;
dropInfo.Effects = DragDropEffects.Move;
}
}
public void Drop(IDropInfo dropInfo)
{
if (dropInfo.Data is VM_Subgroup)
{
var draggedSubgroup = (VM_Subgroup)dropInfo.Data;
var newCollection = (ObservableCollection<VM_Subgroup>)dropInfo.TargetItem;
newCollection.Add((VM_Subgroup)draggedSubgroup.Clone());
}
}
正如你所看到的,我正在尝试两种不同的解决方案:使用我自己的drop处理程序(RequiredSubgroups)和默认处理程序(ExcludedSubgroups)。
如果我从TreeView中拖动一个子组在RequiredSubgroups列表框上,我在newCollection.Add
处得到一个异常,并且在调试器中调查显示dropInfo。TargetItem为Null。我不明白为什么这里是Null
如果我把一个子组从TreeView拖到ExcludedSubgroups ListBox上,这个拖放可以工作,但是它总是从TreeView的父组中移除子组。我已经尝试过在ListBox和TreeView中使用和不使用dd:DragDrop.DragDropCopyKeyState="None"
,无论子组从ListBox中消失。
如果你能帮我弄清楚如何在不从树中删除原始项目的情况下从树中复制到列表中,我将非常感激。
我没有看完整篇文章,但是为了能够复制,你必须定义你的首选按钮而不是
dd:DragDrop.DragDropCopyKeyState="None".
我使用
dd:DragDrop.DragDropCopyKeyState="ControlKey".
打招呼