2012-08-16 15 views
6

Tengo un problema. Uso TreeView en mi proyecto WPF para visualizar mis datos XML. El problema es que cuando edito mi XmlDocument no se actualiza en TreeView. Pero noté que cuando reviso SelectedNode, es mi edición y XmlNode. Entonces mi método de "Edición" funciona bien, pero solo hay un problema en la actualización visual de mi árbol. .Refresh() o .Items.Refresh() tampoco funcionan.WPF TreeView refrescante

Aquí está la plantilla de mi árbol:

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

Éstos son Window.Resources:

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

Aquí es mi árbol:

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

Y aquí es mi código detrás:

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 segunda cosa es, cómo borrar mi árbol con el fin de ser capaz de utilizarlo de nuevo por otros datos (Tengo NullReferenceException al intentar XmlTree.Items.Clear();

Respuesta

11

Después de muchas horas, finalmente encontraron una solución!

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

Hombre eres el mejor! Necesitaba estas líneas mágicas: XmlTree.Items.Refresh(); XmlTree.UpdateLayout(); ¡Muchas gracias, resolvió mi problema! – Alex

+0

Yeee, pueden poner nerviosa a alguien :) – Nickon