我有两个列表框,其中两个列表框都绑定到两个不同的XML文件。 目的是将XmlElements从一个文件拖到另一个文件(ListBox)。
当我从一个填充的ListBox拖动到另一个填充的ListBox时,目标ListBox中的代码非常简单。 但是当目标ListBox为空时,很难获得任何XmlElements,因为ListBox不包含任何项目。
由于未填充目标,因此代码将失败:
XmlElement targetXmlElement = (XmlElement)parent.Items.GetItemAt(0);
所以问题是:
如何从ListBox-target获取XmlDataProvider或XmlDocument:ListBox parent = (ListBox)sender;
另一个问题是目标列表框应该包含子节点列表,即拖动元素的目标。 如何访问父元素?
ListBox dragSource = null;
private void FoodListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
ListBox parent = (ListBox)sender;
dragSource = parent;
object data = GetDataFromListBox(dragSource, e.GetPosition(parent));
if (data != null)
{
DragDrop.DoDragDrop(parent, data, DragDropEffects.Copy);
}
}
#region GetDataFromListBox(Listbox, Point)
private static object GetDataFromListBox(ListBox source, Point point)
{
UIElement element = source.InputHitTest(point) as UIElement;
if(element != null)
{
object data = DependencyProperty.UnsetValue;
while(data == DependencyProperty.UnsetValue)
{
data = source.ItemContainerGenerator.ItemFromContainer(element);
if (data == DependencyProperty.UnsetValue)
{
element = VisualTreeHelper.GetParent(element) as UIElement;
}
if (element == source)
{
return null;
}
}
if(data != DependencyProperty.UnsetValue)
{
return data;
}
}
return null;
}
#endregion
//This listbox is bound to Dataprovider2, Objects dragged into will access the XML target
private void ListBox_Drop(object sender, DragEventArgs e)
{
ListBox parent = (ListBox)sender;
//Get access to the element from the source XML
XmlElement sourceXmlElement = (XmlElement)e.Data.GetData(typeof(XmlElement));
//Get the position of the parent to any Element in the the target list (e.g the zero element)
XmlElement targetXmlElement = (XmlElement)parent.Items.GetItemAt(0);
AppendXmlNode(sourceXmlElement, targetXmlElement);
}
答案 0 :(得分:1)
在WPF中,您不是直接绑定到集合,而是绑定到该集合的default view。
所有集合都有默认的CollectionView。 WPF总是绑定到 查看而不是集合。如果直接绑定到集合, WPF实际上绑定到该集合的默认视图。这个 默认视图由集合的所有绑定共享,这会导致 所有直接绑定到集合以共享排序,过滤, 组和一个默认视图的当前项特征。
您可以从绑定源中提取XmlDocument
,而不是获取已过滤的视图。
private void targetListBox_Drop(object sender, DragEventArgs e)
{
ListBox parent = (ListBox)sender;
//Get access to the element from the source XML
XmlElement sourceXmlElement = (XmlElement)e.Data.GetData(typeof(XmlElement));
//Get access to the document from the target XML
BindingExpression bindingExpression =
parent.GetBindingExpression(ListBox.ItemsSourceProperty);
Binding parentBinding = bindingExpression.ParentBinding;
XmlDataProvider source = (XmlDataProvider)parentBinding.Source;
XmlDocument targetXmldocument = source.Document;
AppendXmlNode(sourceXmlElement, targetXmldocument);
}
一旦掌握了文档,修改就变得轻而易举。
private static void AppendXmlNode(XmlElement element, XmlDocument doc)
{
//Get access to the root node to append child
XmlNode root = doc.SelectSingleNode("/recipelist/recipe[contains(.,'name')]/foodlist");
//Detach element from source XmlDocument
XmlNode clone = doc.ImportNode(element, true);
root.AppendChild(clone);
}
答案 1 :(得分:1)
感谢bab7lon的好评!
代码片段确实将source
返回为null:
BindingExpression bindingExpression = parent.GetBindingExpression(ListBox.ItemsSourceProperty);
Binding parentBinding = bindingExpression.ParentBinding;
XmlDataProvider source = (XmlDataProvider)parentBinding.Source;
但过了一段时间我意识到object sender
实际上包含了一个DataContext。
以下代码解决了我的问题:
private void ListBox_Drop(object sender, DragEventArgs e)
{
ListBox parent = (ListBox)sender;
//Get access to the element from the source XML
XmlElement sourceXmlElement = (XmlElement)e.Data.GetData(typeof(XmlElement));
XmlDataProvider l_context = (XmlDataProvider)parent.DataContext;
XmlDocument l_XmlDoc = l_context.Document;
string l_Xpath = l_context.XPath;
XmlNode l_node = l_XmlDoc.SelectSingleNode(l_Xpath.Replace("/foodlist/foodtype",""));
XmlElement targetXmlElement = (XmlElement)l_node.SelectSingleNode("foodlist");
AppendXmlNode(sourceXmlElement, targetXmlElement);
}
private void AppendXmlNode(XmlElement source, XmlElement target)
{
XmlElement l_source = source;
XmlElement l_target = target;
//Append first the Parent
XmlNode l_nodeToCopy = l_target.OwnerDocument.ImportNode(l_source, true);
l_target.AppendChild(l_nodeToCopy);
XmlDocument l_doc = l_target.OwnerDocument;
Save(l_doc);
}