将XmlElement从一个列表框拖到另一个空的Xml绑定列表框

时间:2017-02-17 15:59:06

标签: c# xml wpf listbox xmldocument

我有两个列表框,其中两个列表框都绑定到两个不同的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);
    }

2 个答案:

答案 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);
    }
相关问题