2017-02-17 1 views
2

둘 다 두 개의 다른 XML 파일에 바인딩되는 두 개의 목록 상자가 있습니다. XmlElements를 한 파일에서 다른 파일 (ListBox)로 드래그하는 것이 목적입니다.하나의 목록 상자에서 다른 빈 Xml 바운드 목록 상자로 XmlElement 끌기

채워진 ListBox에서 채워진 다른 ListBox로 드래그하면 대상 ListBox의 코드가 매우 간단합니다. 그러나 대상 ListBox가 비어있는 경우 ListBox에 항목이 없으므로 XmlElements를 가져 오는 것은 어렵습니다.

대상이 코드에 실패 채워지지 않기 때문에 :

XmlElement targetXmlElement = (XmlElement)parent.Items.GetItemAt(0);

그래서 질문은 다음과 같습니다 어떻게 내가옵니다 대상에서 XmlDataProvider 또는을 XmlDocument의 보류를받을 수 있나요 : ListBox parent = (ListBox)sender;

또 다른 문제점은 target-listbox에 드래그 한 요소의 대상 인 하위 노드 목록이 포함되어야한다는 것입니다. 상위 요소에 대한 액세스 권한을 얻으려면 어떻게해야합니까?

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

xpath는 아무것도 반환하지 않습니다. –

답변

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

감사합니다. bab7lon!

코드 조각

는 생각으로는 null source을 반환했다 :

BindingExpression bindingExpression = parent.GetBindingExpression(ListBox.ItemsSourceProperty); 
Binding parentBinding = bindingExpression.ParentBinding; 
XmlDataProvider source = (XmlDataProvider)parentBinding.Source; 

을하지만 난 object sender 실제로 DataContext에 포함 된 것을 잠시 후에 깨달았다. 다음 코드 내 문제를 해결

:

리스트 박스 타겟은 XPath는 = "/ recipelist/레시피/foodlist/foodtype [포함 ('이름').]의"foodlist 것을 의미 여과
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); 
    } 
+0

내 스 니펫은 XmlDataProvider를 리소스로 사용합니다 (ref [docs] (https://msdn.microsoft.com/en-us/library/ms749287(v=vs.110) .aspx))) . 그런 다음 다시 한 가지 방법으로 고양이를 피하십시오. – bab7lon

관련 문제