Pregunta

Tengo un TreeView cuya ItemsSource se ajusta a un modelo que tengo. 3 niveles de profundidad es un objeto cuyo estado puede cambiar y, en lugar de escribir una visión y modelo de vista para cada etapa (muy larga de negocios) que quería actualizar simplemente usando este código.

Así que, básicamente, tengo un evento que se dispara una vez que mis cambios de modelo, que atraparlo luego encontrar la TreeViewItem asociada a este bit de datos. Mi problema ahora es que no tengo idea de cómo actualizar la unión en él para reflejar el nuevo valor!

¿Alguien puede ayudar?

Sé que esto no es la mejor práctica, pero que realmente no quiere tener que perder el tiempo escribiendo una enorme cantidad de código para actualizar una sola cosa.

Gracias Chris

¿Fue útil?

Solución

Este ejemplo funciona, a pesar de que sólo dos (no 3) niveles de profundidad. Se muestra una sencilla vista de árbol jerárquica de 2 niveles con artículos padre A, B, y C, con los niños numerados (A.1, B.1, etc). Cuando se hace clic en el botón Cambiar nombre B.1, renombra B.1 a "Sylvia".

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace UpdateVanillaBindingValue
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        private DataClass _data;

        public Window1()
        {
            InitializeComponent();
            var data = CreateData();
            DataContext = _data = data;
        }

        private DataClass CreateData()
        {
            return new DataClass
               {
                   Parents=new List<Parent>
                       {
                           new Parent{Name="A",Children=new List<Child>{new Child{Name="A.0"},new Child{Name="A.1"}}},
                           new Parent{Name="B",Children=new List<Child>{new Child{Name="B.0"},new Child{Name="B.1"},new Child{Name="B.2"}}},
                           new Parent{Name="C",Children=new List<Child>{new Child{Name="C.0"},new Child{Name="C.1"}}}
                       }
               };
        }

        private void Rename_Click(object sender, RoutedEventArgs e)
        {
            var parentB = _data.Parents[1];
            var parentBItem = TheTree.ItemContainerGenerator.ContainerFromItem(parentB) as TreeViewItem;
            parentB.Children[1].Name = "Sylvia";

            var parentBItemsSource = parentBItem.ItemsSource;
            parentBItem.ItemsSource = null;
            parentBItem.ItemsSource = parentBItemsSource;
        }
    }

    public class DataClass
    {
        public List<Parent> Parents { get; set; }
    }

    public class Parent
    {
        public string Name { get; set; }
        public List<Child> Children { get; set; }
    }

    public class Child
    {
        public string Name { get; set; }
    }
}

<Window x:Class="UpdateVanillaBindingValue.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid.Resources>
            <DataTemplate x:Key="ChildTemplate">
                <TextBlock Margin="50,0,0,0" Text="{Binding Name}" />
            </DataTemplate>
            <HierarchicalDataTemplate x:Key="ParentTemplate" ItemsSource="{Binding Children}" ItemTemplate="{StaticResource ChildTemplate}">
                <TextBlock Text="{Binding Name}" />
            </HierarchicalDataTemplate>
        </Grid.Resources>
        <TreeView x:Name="TheTree" ItemsSource="{Binding Parents}" ItemTemplate="{StaticResource ParentTemplate}" />
        <Button VerticalAlignment="Bottom" HorizontalAlignment="Center" Content="Rename B.1" Click="Rename_Click" />
    </Grid>
</Window>

Este es un truco, pero re-evalúa la DataTemplate cada vez que se cambia la propiedad ItemsSource.

Lo ideal sería aplicar INotifyPropertyChanged en su clase de objeto modelo que esta TreeViewItem está obligado a, y tienen que desencadena el evento PropertyChanged cuando cambia ese valor. De hecho, usted debe tener cuidado de que no está incurriendo en una pérdida de memoria debido a que no: Encontrar memoria-fugas en aplicaciones de WPF .

Otros consejos

¿Estás seguro de que no sería más fácil de implementar INotifyPropertyChanged en la clase correspondiente?

Parece que usted podría tener que echar un vistazo a los métodos UpdateSource y UpdateTarget.

referencia MSDN para UpdateSource

A pesar de que no estoy totalmente seguro de que esto va a funcionar cuando se ha hecho obligado ItemSource del TreeView en una estructura de datos jerárquica, pero es donde me gustaría empezar a investigar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top