Как отобразить значение XML-узла и дочернего узла на одном уровне WPF treeview?
I have an application which manages audio recordings. In theory, new recording of "My Series" go in a folder "\\Library\My Series" but there are two complications. Firstly, new recordings may come to me with alternate names; for example "Macbeth" might become "William Shakespeare's Macbeth". Secondly, names can contain characters not allowed in folder names - for example "Who Framed Roger Rabbit?". So I have a simple data structure which contains, for each series, the display name for use in the UI, the foldername for use in storage and a list (possibly empty) of aliases, and I have LINQ to retrieve one given another. Here's an example to show the structure of the data file:
<?xml version="1.0" encoding="utf-8"?> <recordings> <series> <seriestitle>Series 1</seriestitle> <seriesfolder>Series 1</seriesfolder> <alias>Series One</alias> <alias>Series 1.0</alias> </series> <series> <seriestitle>Series 2:The Return</seriestitle> <seriesfolder>Series 2_The Return</seriesfolder> <alias>Series Two</alias> </series> <series>Example with title as text of Series node -> This is series three <seriestitle>Series 3 - Why?</seriestitle> <seriesfolder>Series 3 - Why_</seriesfolder> <alias>Series three alias 1</alias> <alias>Series 3.0</alias> <alias>Series 3.0 (Premier)</alias> </series> </recordings>
Я хотел бы добавить представление всех этих данных в свой пользовательский интерфейс, поэтому я играл с WPF TreeView. Я использовал HierarchicalDataTemplate, но столкнулся с проблемой. Я показываю [NodeName][NodeValue], который работает - но дает все содержимое узла для <series>, как и должно быть. Я могу подавить поле "Серия", которое работает, но если я сверну дерево, чтобы получить больше одного экрана, вместо списка названий серий, я получу имя поля снова и снова - не очень полезно для навигации. Вот XAML и codebehind для моего главного окна.
<Window x:Class="XmlDataTree.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:local="clr-namespace:XmlDataTree" Title="XmlData Tree Test" Loaded="Window_Loaded"> <Window.Resources> <!-- Expand all nodes on load for demo --> <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="IsExpanded" Value="{Binding ElementName=chkExpand, Path=IsChecked, TargetNullValue=false}"/> </Style> <HierarchicalDataTemplate x:Key="NodeTemplate"> <StackPanel Orientation="Horizontal" Focusable="False"> <TextBlock x:Name="tbName" Text="{Binding Name}" /> <TextBlock Text=": " /> <TextBox x:Name="tbValue" Text="{Binding Value}" /> </StackPanel> <!-- Hide series data --> <HierarchicalDataTemplate.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding Path=Name.LocalName}" Value="series"/> <Condition Binding="{Binding ElementName=chkHide, Path=IsChecked, TargetNullValue=false}" Value="True"/> </MultiDataTrigger.Conditions> <Setter TargetName="tbValue" Property="Visibility" Value="Collapsed"/> </MultiDataTrigger> </HierarchicalDataTemplate.Triggers> <HierarchicalDataTemplate.ItemsSource> <Binding Path="Elements" /> </HierarchicalDataTemplate.ItemsSource> </HierarchicalDataTemplate> </Window.Resources> <Grid Margin="4"> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal"> <TextBlock Text="Expand Tree" /> <CheckBox Name="chkExpand" IsChecked="True" /> <TextBlock Text="Hide Series" Margin="10,0"/> <CheckBox Name="chkHide" IsChecked="False" /> </StackPanel> <TreeView Name="trview" ItemsSource="{Binding Path=Root.Elements}" ItemTemplate="{StaticResource NodeTemplate}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> </StackPanel> </Grid> </Window>
using System.Windows; using System.Xml.Linq; namespace XmlDataTree { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { XDocument xDoc = new XDocument(); xDoc = XDocument.Load(System.IO.Path.GetFullPath(System.AppDomain.CurrentDomain.BaseDirectory) + "aliases.xml"); trview.DataContext = xDoc; } } }
Если вы запустите эту программу, то увидите, что поле "серия" содержит много информации. Если вы скроете поле серии, установив флажок, то сможете увидеть данные более четко. С другой стороны, если вы свернете дерево, поставив галочку в другом поле, вы увидите гораздо больше рядов, и поле "ряд" не слишком страшно в качестве индекса. Но если вы сделаете и то, и другое. все, что вы получаете, - это список слов "серия" снова и снова.
Есть ли способ для "&ЛТ;серии&ГТ;" развал области/расширить возможности быть сохранены, но для отображения &ЛТ;seriestitle&ГТ; childnode, а не в <серии&ГТ; сам узел? Я чувствую, что должен быть в состоянии управлять чем-то, заменив
<Setter TargetName="tbValue" Property="Text" Value="{Value}"/>
с
<Setter TargetName="tbValue" Property="Text" Value="{Binding Path=node::childnode[seriestitle].text()"/>
Что я уже пробовал:
Я потратил много времени на поиск в Google и путался между Path и XPath, XDocuments и XmlDocuments и многими другими. Наверное, это не поможет, потому что я не профессионал, это просто хобби ;-)
Все предложения с благодарностью получены!