2012-08-16 4 views
6

Ho un problema. Io uso TreeView nel mio progetto WPF per visualizzare i miei dati XML. Il problema è che quando modifico il mio XmlDocument non viene aggiornato in TreeView. Ma ho notato che quando controllo lo SelectedNode, è il mio editted e XmlNode. Quindi il mio metodo "Modifica" funziona bene, ma c'è solo un problema nell'aggiornamento visivo del mio albero. .Refresh() o .Items.Refresh() non funzionano neanche.WPF TreeView refreshing

Ecco il modello del mio albero:

<DataTemplate x:Key="AttributeTemplate"> 
    <StackPanel Orientation="Horizontal" 
      Margin="3,0,0,0" 
      HorizontalAlignment="Center"> 
     <TextBlock Text="{Binding Path=Name}" 
      Foreground="{StaticResource xmAttributeBrush}" FontFamily="Consolas" FontSize="8pt" /> 
     <TextBlock Text="=&quot;" 
      Foreground="{StaticResource xmlMarkBrush}" FontFamily="Consolas" FontSize="8pt" /> 
     <TextBlock Text="{Binding Path=Value, Mode=TwoWay}" 
      Foreground="{StaticResource xmlValueBrush}" FontFamily="Consolas" FontSize="8pt" /> 
     <TextBlock Text="&quot;" 
      Foreground="{StaticResource xmlMarkBrush}" FontFamily="Consolas" FontSize="8pt" /> 
    </StackPanel> 
</DataTemplate> 

<HierarchicalDataTemplate x:Key="NodeTemplate"> 
    <StackPanel Orientation="Horizontal" Focusable="False"> 
     <TextBlock x:Name="tbName" Text="?" FontFamily="Consolas" FontSize="8pt" /> 
     <ItemsControl 
      ItemTemplate="{StaticResource AttributeTemplate}" 
      ItemsSource="{Binding Path=Attributes}" 
      HorizontalAlignment="Center"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <StackPanel Orientation="Horizontal"/> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
     </ItemsControl> 
    </StackPanel> 
    <HierarchicalDataTemplate.ItemsSource> 
     <Binding XPath="*" /> 
    </HierarchicalDataTemplate.ItemsSource> 
    <HierarchicalDataTemplate.Triggers> 
     <DataTrigger Binding="{Binding Path=NodeType}" Value="Text"> 
      <Setter TargetName="tbName" Property="Text" Value="{Binding Path=Value, Mode=TwoWay}"/> 
     </DataTrigger> 
     <DataTrigger Binding="{Binding Path=NodeType}" Value="Element"> 
      <Setter TargetName="tbName" Property="Text" Value="{Binding Path=Name}"/> 
     </DataTrigger> 
    </HierarchicalDataTemplate.Triggers> 
</HierarchicalDataTemplate> 

<Style x:Key="TreeViewAllExpandedStyle" TargetType="{x:Type TreeView}"> 
    <Style.Resources> 
     <Style TargetType="TreeViewItem"> 
      <Setter Property="IsExpanded" Value="True" /> 
     </Style> 
    </Style.Resources> 
</Style> 

<Style x:Key="TreeViewAllCollapsedStyle" TargetType="{x:Type TreeView}"> 
    <Style.Resources> 
     <Style TargetType="TreeViewItem"> 
      <Setter Property="IsExpanded" Value="False" /> 
     </Style> 
    </Style.Resources> 
</Style> 

Ecco Window.Resources:

<Window.Resources> 
    <XmlDataProvider x:Key="XmlData" /> 
</Window.Resources> 

Ecco il mio albero:

<TreeView x:Name="XmlTree" Grid.Row="1" 
     ItemsSource="{Binding Source={StaticResource XmlData}, XPath=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
     ItemTemplate="{StaticResource NodeTemplate}" 
     SelectedItemChanged="XmlTree_SelectedItemChanged" /> 

Ed ecco il mio codice dietro:

private XmlDocument _xml; 
private XmlElement _selectedElement; 
private XmlDataProvider _xmlDataProvider; 

private void MainWindow_Load(object sender, EventArgs e) 
{ 
    XmlTree.Style = (Style)FindResource("TreeViewAllExpandedStyle"); 
    _xmlDataProvider = FindResource("XmlData") as XmlDataProvider; 
} 

private void OpenXmlFile(string filePath) 
{ 
    _xml = new XmlDocument(); 
    _xml.Load(filePath); 

    _xmlDataProvider.Document = _xml; 
} 

private void SaveChangesButton_Click(object sender, EventArgs e) 
{ 
    Dictionary<string, string> newAttributes = GetChangedAttributes(); 
    foreach (KeyValuePair<string, string> pair in newAttributes) 
    { 
     _selectedElement.SetAttribute(pair.Key, pair.Value); 
    } 

    RefreshViews(); 
} 

private void RefreshViews() 
{ 
    // now I don't know what to do here, any Refresh doesn't work:S 
} 

La seconda cosa è, come cancellare il mio albero, al fine di essere in grado di utilizzarlo ancora per altri dati (devo NullReferenceException durante il tentativo XmlTree.Items.Clear();

risposta

11

Dopo molte ore finalmente trovato una soluzione!

private void RefreshViews() 
{ 
    XmlEditor.Clear(); 
    XmlEditor.Text = IndentXml(); 

    UnselectSelectedItem(); 

    XmlTree.Items.Refresh(); 
    XmlTree.UpdateLayout(); 
} 

private void UnselectSelectedItem() 
{ 
    if (XmlTree.SelectedItem != null) 
    { 
     var container = FindTreeViewSelectedItemContainer(XmlTree, XmlTree.SelectedItem); 
     if (container != null) 
     { 
      container.IsSelected = false; 
     } 
    } 
} 

private static TreeViewItem FindTreeViewSelectedItemContainer(ItemsControl root, object selection) 
{ 
    var item = root.ItemContainerGenerator.ContainerFromItem(selection) as TreeViewItem; 
    if (item == null) 
    { 
     foreach (var subItem in root.Items) 
     { 
      item = FindTreeViewSelectedItemContainer((TreeViewItem)root.ItemContainerGenerator.ContainerFromItem(subItem), selection); 
      if (item != null) 
      { 
       break; 
      } 
     } 
    } 

    return item; 
} 
+4

Man sei il migliore! Avevo bisogno di queste linee magiche: XmlTree.Items.Refresh(); XmlTree.UpdateLayout(); Grazie mille, ho risolto il mio problema! – Alex

+0

Sì, possono rendere qualcuno nervoso :) – Nickon