2012-08-16 14 views
6

Mam problem. Używam TreeView w moim projekcie WPF do wizualizacji moich danych XML. Problem polega na tym, że kiedy edytuję moje XmlDocument, nie odświeżam w TreeView. Ale zauważyłem, że kiedy sprawdzam SelectedNode, to jest on mój edited i XmlNode. Tak więc moja metoda "Edycja" działa dobrze, ale jest tylko problem z wizualnym odświeżeniem mojego drzewa. .Refresh() lub .Items.Refresh() również nie działają.Odświeżanie drzewa WPF

Oto szablon mojego drzewa:

<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> 

Oto Window.Resources:

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

Oto moje drzewo:

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

A oto mój kod za:

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 
} 

Drugą rzeczą jest, jak wyczyścić moje drzewo, aby być w stanie użyć go ponownie na kolejne dane (Mam NullReferenceException starając XmlTree.Items.Clear();

Odpowiedz

11

Po wielu godzinach w końcu znaleźć rozwiązanie!

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

Człowiek, który jesteś najlepszy! Potrzebowałem tych magicznych linii: XmlTree.Items.Refresh(); XmlTree.UpdateLayout(); Dziękuję bardzo, rozwiązałeś mój problem! – Alex

+0

Yeee, mogą sprawić, że ktoś się zdenerwuje :) – Nickon