xtensa1408
xtensa1408

Reputation: 594

My treeView populate a strange children : WPF MVVM

I constructed a treeView WPF MVVM with the help of this very good article Then I created a contextMenu for some node that allowed me to add children from selected parent.

The problem is if I click on "Add" without expanding manually the selected node(parent), a strange child is created automatically in addition to the node expected to be generated when clicking on "Add".

I tried to detect the problem so I change the code below from:

<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />

to:

<Setter Property="IsExpanded" Value="True" />

Image 1 below shows the result of this test or Image 2 shows what my treeView must show.

enter image description here

Rq: I used image from the article that I talked about it. Also, I used the same approach described in the article (including the class TreeViewItemViewModel.cs )

<TreeView ItemsSource="{Binding Regions}" IsEnabled="{Binding EnableTree}" > <TreeView.ItemContainerStyle> <!-- This Style binds a TreeViewItem to a TreeViewItemViewModel. --> <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> <Setter Property="FontWeight" Value="Normal" /> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="FontWeight" Value="Bold" /> </Trigger> </Style.Triggers> </Style> </TreeView.ItemContainerStyle> <TreeView.Resources> <ContextMenu x:Key="AddCity" ItemsSource="{Binding AddCityItems}"/> <HierarchicalDataTemplate DataType="{x:Type local:StateViewModel}" ItemsSource="{Binding Children}" > <StackPanel Orientation="Horizontal" ContextMenu="{StaticResource AddCity}"> <Image Width="16" Height="16" Margin="3,0" Source="Images\Region.png" /> <TextBlock Text="{Binding RegionName}" /> </StackPanel> </HierarchicalDataTemplate> </TreeView.Resources>

`public class StateViewModel : TreeViewItemViewModel {

   readonly State _state;
   public ICommand AddCityCommand { get; private set; }
   public List<MenuItem> AddCityItems { get; set; }

    public StateViewModel(State state, RegionViewModel parentRegion)
        : base(parentRegion, true)
    {
        _state = state;
        AddCityItems = new List<MenuItem>();
        AddCityCommand = new DelegateCommand<CancelEventArgs>(OnAddCityCommandExecute, OnAddCityCommandCanExecute);
        AddCityItems.Add(new MenuItem() { Header = "Add City", Command = AddCityCommand });
    }

    public string StateName
    {
        get { return _state.StateName; }
    }

    protected override void LoadChildren()
    {
        foreach (City city in Database.GetCities(_state))
            base.Children.Add(new CityViewModel(city, this));
    }


    bool OnAddCityCommandCanExecute(CancelEventArgs parameter)
    {
        return true;
    }

    public void OnAddCityCommandExecute(CancelEventArgs parameter)
    {
        var myNewCity = new city();
        Children.Add(new CityViewModel(myNewCity, this));
    }
}`

BTW, if I expand my parent node then I click into add City, I have the result as expected but if I don't expand parent node and I click on contextMenu I have another child created in addition to the child I want to create

EDIT I add the statemnt below to my add() method and I don't have any problem now:

public void OnAddCityCommandExecute(CancelEventArgs parameter)
    {
        var myNewCity = new city();
        Children.Add(new CityViewModel(myNewCity, this));
        //the modif
        this.Children.Remove(DummyChild);
    }

Upvotes: 0

Views: 1392

Answers (1)

cscmh99
cscmh99

Reputation: 2781

I can see the bug in your code.

Here's the steps to reproduce:

  1. At state node (never expand it first)
  2. Without Expanding the Child upfront, Your StateViewModel's Children contain a DummyChild.
  3. Added 1 new City into the list which cause the HasDummyChild won't work as the count is now 2 in Children's list
  4. Then when you try to expand the node to check the result. Your treelist will have the DummyChild which is a base class that screwed up everything

So, basically that's why "Expand" first is the key of your problem as at that time HasDummyChild still working as it compares .Count == 1. The tree won't remove the DummyChild out from your Children list if you add an extra child to the list that makes .Count == 2.

ADDITIONAL INFO as requested

Just change the HasDummyChild as the following

    public bool HasDummyChild
    {
        //get { return this.Children.Count == 1 && this.Children[0] == DummyChild; }
        get { return Children.Any() && Children.Contains(DummyChild); }
    }

enter image description here

Upvotes: 1

Related Questions