Question

J'ai un TreeView dont ItemsSource est réglé sur un modèle que j'ai. 3 niveaux de profondeur est un objet dont l'état peut changer et, plutôt que d'écrire une vue et ViewModel pour chaque étape (d'affaires très long), je voulais mettre à jour que ce code à l'aide.

Donc, fondamentalement, j'ai un événement qui est tiré une fois mes mises à jour du modèle, j'attraper trouver alors la TreeViewItem associée à ce bit de données. Mon problème est maintenant je ne sais pas comment mettre à jour la liaison sur elle pour refléter la nouvelle valeur!

Quelqu'un peut-il aider?

Je sais que ce n'est pas la meilleure pratique, mais je ne veux pas vraiment avoir à perdre du temps à écrire une énorme quantité de code à simplement mettre à jour une chose.

Merci Chris

Était-ce utile?

La solution

Cet exemple fonctionne, mais il est seulement deux niveaux (et non 3) de profondeur. Il montre un simple hiérarchique TreeView 2 niveaux avec des éléments parents A, B et C, avec les enfants numérotés (A.1, B.1, etc.). Lorsque le bouton Renommer B.1 est cliqué, il renomme B.1 à « 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>

Ceci est un hack, mais il réévalue le DataTemplate chaque fois qu'il est des changements de propriété ItemsSource.

Idéalement, vous mettre en œuvre INotifyPropertyChanged sur votre classe d'objets de modèle que ce TreeViewItem est lié, et avoir le feu lorsque l'événement PropertyChanged que les changements de valeur. En fait, vous devriez faire attention que vous n'êtes pas subir une fuite de mémoire, car il ne fait pas: Trouver des fuites de mémoire dans les applications WPF .

Autres conseils

Êtes-vous sûr qu'il ne serait pas plus facile à mettre en œuvre INotifyPropertyChanged sur la classe concernée?

On dirait que vous pourriez avoir besoin de jeter un oeil sur les méthodes de UpdateSource et UpdateTarget.

référence MSDN pour UpdateSource

Bien que je ne suis pas tout à fait sûr que cela fonctionnera lorsque vous avez réellement lié la ItemSource du TreeView à une structure de données hiérarchique, mais il est là que je commencerais enquête.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top