I've been trying to build a TreeView
with a Hierarchical setup filled with Checkboxes. And such, in order to retrieve which checkboxes are checked later in the code. And in between others, two problems are still on my plate: 1. However I try to give the TreeView
's ItemsSource
as a Binding
, the TreeView appears empty when the program is running. This does not happen if I set ItemsSource
manually in the code-behind. 2. I also have a problem with getting the IsChecked
information of the Checkboxes, since I can't rely on the binding. Here's the interesting part of the code I've come up with so far: --- XAML ---
<TreeView x:Name="TreeView_Add_TagSelector" ItemsSource="{Binding TagCheckboxesTreeSource}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:TagCheckboxNode}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
--- C# ---
public partial class MainWindow : Window
{
ObservableCollection<TagCheckboxNode> tagCheckboxesTreeSource;
List<Tag> selectedTags;
// Other non-related attributes...
public MainWindow()
{
// Other non-related stuff...
// I've been trying my loading function before and after InitializeComponent just in case...
LoadTagTree();
InitializeComponent();
LoadTagTree();
}
private ObservableCollection<TagCheckboxNode> TagCheckboxesTreeSource { get => tagCheckboxesTreeSource; set => tagCheckboxesTreeSource = value; }
// Other non-related properties...
private void LoadTagTree()
{
ObservableCollection<TagCheckboxNode> categories = new ObservableCollection<TagCheckboxNode>();
foreach (XmlElement category in database.XmlCategories)
{
TagCheckboxNode categoryItem = new TagCheckboxNode(null, category.GetAttribute("name"));
foreach(XmlElement tag in category)
{
TagCheckboxNode tagItem = new TagCheckboxNode(categoryItem, tag.GetAttribute("name"));
categoryItem.Children.Add(tagItem);
}
categories.Add(categoryItem);
}
TagCheckboxesTreeSource = categories;
//TreeView_Add_TagSelector.ItemsSource = categories; // This works but the above doesn't
}
// I'm also going to need an event handler which fires up when a checkbox's state changes.
private void TreeView_Add_TagSelector_SelectionChanged(object sender, RoutedEventArgs e)
{
// To fill up...
}
}
class TagCheckboxNode : INotifyPropertyChanged
{
TagCheckboxNode parent;
ObservableCollection<TagCheckboxNode> children;
bool? isChecked;
bool shouldParentAlsoCheck;
string name;
public TagCheckboxNode(TagCheckboxNode parent, string name, bool shouldParentAlsoCheck = true)
{
this.parent = parent;
this.name = name;
this.isChecked = false;
this.children = new ObservableCollection<TagCheckboxNode>();
this.shouldParentAlsoCheck = shouldParentAlsoCheck;
}
public ObservableCollection<TagCheckboxNode> Children => children;
public bool ShouldParentAlsoCheck => shouldParentAlsoCheck;
public string Name => name;
public bool? IsChecked
{
get { return isChecked; }
set { SetIsChecked(value, true, shouldParentAlsoCheck); }
}
public bool HasChildNodes {
// Non-relevant code
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
void SetIsChecked(bool? value, bool updateChildren, bool updateParent) {
// More non-relevant code
// Just be aware that OnPropertyChanged() is called inside here.
}
void VerifyCheckState() {
// Non-relevant code again
}
}
If you need more information feel free to ask. Thank you for your time in advance.
biguest
Aucun commentaire:
Enregistrer un commentaire