I have 2 list boxes (ListA and ListB) that display data from different entities (EntityA, EntityB). These entities are related - EntityA has a property of a collection of EntityB. I want to be able to use drag and drop behaviour in order to add items from ListB into the collection of the dropped item in ListA.
To cla开发者_JAVA技巧rify, I don't want to add ListItemB into the collection of the selected ListItemA, I want to add it into the collection of the list item that I drop it onto (the ListItemA that the mouse is over when I release).
Using ListBoxDragDropTarget, is it possible for a ListBoxItem to be the drop target, instead of the listbox itself?
Any suggestions as to a solution for this scenario?
It can be done by creating two ListBoxes, as you described, one bound to an ObservableCollection<EntityA>
and one bound to an ObservableCollection<EntityB>
. EntityA contains an ObservableCollection<EntityB>
as a property. The ListBox items of EntityA are templated to display the child collection of EntityB's as a ListBox. The ListBoxDragDropTarget is specified in this ItemTemplate, rather than the parent. Here is some XAML to demonstrate:
<ListBox Name="listOfEntityA">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding EntityName}" />
<toolKit:ListBoxDragDropTarget AllowDrop="True" AllowedSourceEffects="All">
<ListBox ItemsSource="{Binding ChildEntityBs}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding EntityName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</toolKit:ListBoxDragDropTarget>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<toolKit:ListBoxDragDropTarget AllowDrop="True" AllowedSourceEffects="All">
<ListBox Name="listOfEntityB" />
</toolKit:ListBoxDragDropTarget>
After a bit of work I think I have it:
<StackPanel Orientation="Horizontal">
<Controls:ListBoxDragDropTarget AllowDrop="True">
<ListBox x:Name="FromBox" Width="200" ItemsSource="{Binding IssueList}" DisplayMemberPath="Name"/>
</Controls:ListBoxDragDropTarget>
<Controls:ListBoxDragDropTarget AllowDrop="True" Drop="ToBoxDragDropTarget_Drop">
<ListBox x:Name="ToBox" Width="150" ItemsSource="{Binding ObjectiveList}" DisplayMemberPath="Name" Margin="80,0,0,0" />
</Controls:ListBoxDragDropTarget>
<TextBlock x:Name="UpdateText"/>
</StackPanel>
and the codebehind (which will now be refactored into my ViewModel):
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
IssueList = new ObservableCollection<Issue>
{
new Issue{ ID = 1, Name="One"},
new Issue{ ID = 2, Name="Two"},
new Issue{ ID = 3, Name="Three"},
new Issue{ ID = 4, Name="Four"},
new Issue{ ID = 5, Name="Five"},
};
ObjectiveList = new ObservableCollection<Objective>
{
new Objective {ID = 10, Name = "Ten"},
new Objective {ID = 11, Name = "Eleven"},
new Objective {ID = 12, Name = "Twelve"},
new Objective {ID = 13, Name = "Thirteen"},
new Objective {ID = 14, Name = "Fourteen"},
};
LayoutRoot.DataContext = this;
}
public ObservableCollection<Issue> IssueList { get; set; }
public ObservableCollection<Objective> ObjectiveList { get; set; }
private void ToBoxDragDropTarget_Drop(object sender, Microsoft.Windows.DragEventArgs e)
{
var droppedOnObjective = ((FrameworkElement)e.OriginalSource).DataContext as Objective;
var args = e.Data.GetData(typeof(ItemDragEventArgs)) as ItemDragEventArgs;
if (args != null)
{
var draggedItems = args.Data as SelectionCollection;
var draggedItem = draggedItems[0];
if (droppedOnObjective != null)
{
var draggedIssue = (Issue)draggedItem.Item;
if (!droppedOnObjective.Issues.Contains(draggedIssue))
{
droppedOnObjective.Issues.Add(draggedIssue);
UpdateText.Text = string.Format("Issue <{0}> added to Objective <{1}>", draggedIssue.Name, droppedOnObjective.Name);
}
else
{
UpdateText.Text = string.Format("Objective <{0}> already contains Issue <{1}>", droppedOnObjective.Name, draggedIssue.Name);
}
}
else
UpdateText.Text = "selections or dropOnObjective is null";
}
else
UpdateText.Text = "args null";
}
}
public class Issue
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Objective
{
public int ID { get; set; }
public string Name { get; set; }
public List<Issue> Issues { get; set; }
public Objective()
{
Issues = new List<Issue>();
}
}
精彩评论