- 建立一 TreeView ,為了能拖拽及處理拖拽動作,需要在 TreeView 中添加代碼:
AllowDrop="True"PreviewDragOver="treeView_PreviewDragOver"PreviewDrop="treeView_PreviewDrop
- 允許拖拽的資料對象中的資料存放區格式應該為文本資料或檔案放置格式,所以 PreviewDragOver 時判斷:
if (e.Data.GetDataPresent(DataFormats.Text, false) || e.Data.GetDataPresent(DataFormats.FileDrop, false))
並設定當前相應拖放效果的:
e.Effects = DragDropEffects.Copy; 或:
e.Effects = DragDropEffects.None;
因為在 XAML 中綁定 XML :
<XmlDataProvider x:Key="xmlDataProvider"> <x:XData>
同理, C# 參照著,以便綁定到合適的資料來源格式:
XmlDataProvider xmlDataProvider = new XmlDataProvider();
- 根據不同資料格式處理資料:
if (e.Data.GetDataPresent(DataFormats.Text, false)){ string text = e.Data.GetData(DataFormats.Text, false).ToString(); XmlDocument xd = new XmlDocument(); xd.LoadXml(text); xmlDataProvider.Document = xd;}else if (e.Data.GetDataPresent(DataFormats.FileDrop, false)){ string fileName = (e.Data.GetData(DataFormats.FileDrop, false) as string[]).FirstOrDefault(); xmlDataProvider.Source = new Uri(fileName);}
- 最後別忘記:
treeview.DataContext = xmlDataProvider;
注意,這相應於在 XAML 中設定 DataContext 屬性,但 XAML 中仍然需要設定 ItemsSource 屬性:
ItemsSource="{Binding}" <!--若沒 ItemsSource="{Binding XPath=*}" 則原 XML 外少包一層,導致無法顯示最外層的非 Element 節點-->
接下來開始設計 TreeView 外觀:
<HierarchicalDataTemplate x:Key="ItemTemplate" ItemsSource="{Binding}"> <!--ItemsSource="{Binding}"才能顯示子節點資料--> <StackPanel Orientation="Horizontal"> <CheckBox x:Name="checkBox" Opacity="0"> </CheckBox> <TextBlock x:Name="text" Text="?" /> </StackPanel></HierarchicalDataTemplate>
CheckBox 將處理 XmlElement 相關顯示。
- 處理 NodeType 為 Element 比較複雜,需要多重綁定和
<HierarchicalDataTemplate.Triggers> <DataTrigger Binding="{Binding NodeType}" Value="Element"> <Setter TargetName="text" Property="Text"> <Setter.Value> <MultiBinding Converter="{StaticResource textConverter}"> <Binding></Binding> <Binding ElementName="checkBox" Path="IsChecked"></Binding> </MultiBinding > </Setter.Value> </Setter> <Setter TargetName="checkBox" Property="Opacity" Value="1"> </Setter> </DataTrigger></HierarchicalDataTemplate.Triggers>
上面的<Binding></Binding>為了在轉換中擷取 Element:
XmlElement element = values[0] as XmlElement;
所以可以對 element 對象作處理,如屬性:
foreach (XmlAttribute e in element.Attributes)
注意操作轉換要在 XAML 中增加:
xmlns:local="clr-namespace:WPF_XML_AnyStyle"
<local:TextConverter x:Key="textConverter"></local:TextConverter>
如果 checkBox 選中則只是:
return element.Name;
沒選可以返回如屬性等的值。(詳見代碼)
為了能顯示其他類型的 XML 節點:
<DataTrigger Binding="{Binding NodeType}" Value="Element">
這裡的 ="Element" 可以換成如 "Comment" 等的 XmlNodeType 枚舉類型。
- 請點擊下載樣本(內含一個樣本的XML檔案)。
想想:
- XML中不能出現任何中文字元,結構也必須正確,否則將無法產生 TreeView。
- 沒有用消極式載入技術(XML檔案直接在記憶體中),但點擊開啟節點才消極式載入顯示內容。(調試 textConverter 可知)
- 若拖拽多個檔案,只處理“第一個”。(見FirstOrDefault())(與點擊的順序無關,真怪異!)
- 本文只處理了常用的節點類型。如果要處理 XML 的其他 XmlNodeType 的節點類型(如 <!DOCTYPE...>,類型為 DocumentType),可以在 VS 中設斷點調試,在“快速監視”視窗中查看獲得的 Document(或 Element)的相關父子屬性,然後再添加相應的 DataTrigger ,設定其 Value="......"。如果對象複雜可參照 MultiBinding 用轉換返回所需要顯示的資料。
- 歡迎意見或建議!