Pergunta

Eu tenho um TreeView cuja ItemsSource está definido para um modelo que eu tenho. 3 níveis de profundidade é um objeto cujo estado pode mudar e, em vez de escrever uma View e ViewModel para cada fase (muito demorado negócio) Eu queria apenas atualizar esse código usando.

Então, basicamente eu tenho um evento que é disparado uma vez as minhas actualizações modelo, eu pegá-lo, em seguida, encontrar o TreeViewItem associado a este bit de dados. Meu problema agora é que não tenho idéia sobre como atualizar a ligação nele para refletir o novo valor!

alguém pode ajudar?

Eu sei que esta não é a melhor prática, mas eu realmente não quero ter que perder tempo escrevendo uma enorme quantidade de código para apenas atualizar uma coisa.

Graças Chris

Foi útil?

Solução

Este exemplo funciona, mas é apenas dois (não 3) níveis de profundidade. Ela mostra um simples 2-TreeView nível hierárquico com itens pai A, B, e C, com as crianças numeradas (A.1, B.1, etc). Quando o botão Rename B.1 é clicado, ele renomeia B.1 para "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 é um hack, mas re-avalia o DataTemplate cada vez que é ItemsSource alterações de propriedade.

O ideal seria implementar INotifyPropertyChanged em sua classe de objeto modelo que esta TreeViewItem é obrigado a, e tê-lo disparar o evento PropertyChanged quando esse valor muda. Na verdade, você deve ter cuidado para que você não está incorrer em um vazamento de memória porque ele não faz: Encontrando-memória vazamentos em aplicações WPF .

Outras dicas

Você tem certeza que não seria mais fácil de implementar INotifyPropertyChanged na classe relevante?

Parece que você pode precisar de dar uma olhada nos métodos UpdateSource e UpdateTarget.

referência MSDN para UpdateSource

Embora eu não estou totalmente certo de que isso vai funcionar quando você realmente obrigado ItemSource do TreeView a uma estrutura hierárquica de dados, mas é onde eu iria começar a investigar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top