My issue is that when i tried to create dynamically a TreeView with checkbox, but the TreeView is empty.
After some research i tried this :
Here is my treeview in XAML
<TreeView x:Name="TrwDonneesXml"
HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="8" Grid.Column="0"
Height="420"
Width="500"
Margin="10,10,10,10"
Background="LightGray"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ItemsSource="{Binding Root, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="True">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type models:CheckableItem}" ItemsSource="{Binding Childrens, Mode=TwoWay}">
<StackPanel Orientation="Horizontal" >
<!--These elements are bound to a CheckableItem object.-->
<CheckBox Focusable="False"
Content="{Binding Name}"
IsChecked="{Binding IsChecked, Mode=TwoWay}"
VerticalAlignment="Center"/>
<!--<TextBlock Text="{Binding Name}"
Margin="2,0"/>-->
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Here is my ViewModel
namespace AsurEnvironnement.SynchronisationModule.ViewModels
{
public class Synchronisation2UserControlViewModel : ViewModelBase
{
[...]
public ObservableCollection<CheckableItem> Root = new ObservableCollection<CheckableItem>();
ObservableCollection<CheckableItem> rootAChildrens = new ObservableCollection<CheckableItem>();
[...]
public override async Task InitializeStepAsync()
{
try
{
ObservableCollection<CheckableItem> rootAChildrens = new ObservableCollection<CheckableItem>();
ObservableCollection<CheckableItem> rootBChildrens = new ObservableCollection<CheckableItem>();
CheckableItem rootA = new CheckableItem() { Name = "RootA" };
CheckableItem childrenA1 = new CheckableItem() { Name = "ChildrenA1" };
CheckableItem childrenA2 = new CheckableItem() { Name = "ChildrenA2" };
rootAChildrens.Add(childrenA1);
rootAChildrens.Add(childrenA2);
rootA.Childrens = rootAChildrens;
CheckableItem rootB = new CheckableItem() { Name = "RootB" };
CheckableItem childrenB1 = new CheckableItem() { Name = "ChildrenB1" };
rootBChildrens.Add(childrenB1);
rootB.Childrens = rootBChildrens;
CheckableItem rootC = new CheckableItem() { Name = "RootC" };
Root.Add(rootA);
Root.Add(rootB);
Root.Add(rootC);
[...]
}
catch (Exception ex)
{
ProcessSnackBar(ex.Message);
_logger.LogError(ex.Message, ex);
}
finally
{
[...]
}
}
[...]
}
Here is my Model
namespace AsurEnvironnement.SynchronisationModule.Models
{
public class CheckableItem : DataModelBase, INotifyPropertyChanged
{
private bool? _isChecked;
public ObservableCollection<CheckableItem> Childrens;
public bool? IsChecked
{
get { return _isChecked; }
set
{
_isChecked = value;
foreach(CheckableItem children in Childrens)
{
children.IsChecked = true;
}
}
}
public string Name { get; set; }
}
}
I tried to check with Console.WriteLine(TrwDonneesXml.HasItems);
to see if the data exist but can't be seen but the result is false so i checked in debug mode TrwDonneesXml.ItemsSource is null.
But i realy don't understand why.
The TreeView
is empty due to your semantic mistake which causes the TreeView.ItemsSource
binding to fail.
This is a field:
public ObservableCollection<CheckableItem> Root;
This is a property:
public ObservableCollection<CheckableItem> Root { get; set; }
You are basically initializing a public field using a field initializer:
public ObservableCollection<CheckableItem> Root
= new ObservableCollection<CheckableItem>();
However, in WPF you can only bind to public properties and not to fields.
The correct definition must be:
public ObservableCollection<CheckableItem> Root { get; }
= new ObservableCollection<CheckableItem>();