jeudi 10 août 2017

WPF treeview with checkboxes, where are my checked objects?

I am looking now hours for a solution for this problem: I want to develop a treeview, populated with checkboxes, but I can't get the checked items out of it.

The helper class looks like this:

  class ArchfabTreeViewItemViewHelper : System.Windows.DependencyObject
{
    public string Key { get; set; }
    public string Value { get; set; }
    public bool IsChecked { get; set; }
    public static readonly System.Windows.DependencyProperty IsCheckedProperty = System.Windows.DependencyProperty.RegisterAttached("IsChecked", typeof(bool?), typeof(ArchfabTreeViewItemViewHelper), new System.Windows.PropertyMetadata(false, new System.Windows.PropertyChangedCallback(OnIsCheckedPropertyChanged)));
    public static readonly System.Windows.DependencyProperty ParentProperty = System.Windows.DependencyProperty.RegisterAttached("Parent", typeof(object), typeof(ArchfabTreeViewItemViewHelper));

    public ArchfabTreeViewItemViewHelper() { }

    public ArchfabTreeViewItemViewHelper(string tag, string value)
    {
        this.Key = tag;
        this.Value = value;
        //this.IsChecked = false;
    }

    //methods
    private static void OnIsCheckedPropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
    {
        ArchfabTreeViewItemViewHelper helper = (ArchfabTreeViewItemViewHelper)d;
        ArchfabTreeViewItemViewHelper.SetIsChecked(d.GetValue(ArchfabTreeViewItemViewHelper.ParentProperty) as System.Windows.DependencyObject, true);
    }

I guess, I skipped something important while generating the HierarchialDataTemplate. Here is the template :

class ArchfabHierarchialDataTemplate : System.Windows.HierarchicalDataTemplate
{

    private static ArchfabHierarchialDataTemplate NewCheckBoxTemplate()
    {
        ArchfabHierarchialDataTemplate resultTemplate = new ArchfabHierarchialDataTemplate();

        //stackpanel
        System.Windows.FrameworkElementFactory stackpanel = new System.Windows.FrameworkElementFactory(typeof(ArchfabContainer)) { Name = "Parent" };
        stackpanel.SetValue(System.Windows.FrameworkElement.HeightProperty, 23.00);
        stackpanel.SetValue(System.Windows.FrameworkElement.WidthProperty, 300.00);
        stackpanel.SetValue(System.Windows.FrameworkElement.MarginProperty, new System.Windows.Thickness(2));
        stackpanel.SetValue(ArchfabContainer.BackgroundProperty, new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.LightSteelBlue));

        //checkbox
        //fields and properties
        System.Windows.FrameworkElementFactory checkbox = new System.Windows.FrameworkElementFactory(typeof(ArchfabCheckBox)) { Name = "checkBox" };
        checkbox.SetValue(System.Windows.FrameworkElement.HeightProperty, 23.00);
        checkbox.SetValue(System.Windows.FrameworkElement.WidthProperty, 300.00);
        checkbox.SetValue(System.Windows.FrameworkElement.MarginProperty, new System.Windows.Thickness(2));
        checkbox.SetBinding(ArchfabCheckBox.ContentProperty, new System.Windows.Data.Binding() { Path = new System.Windows.PropertyPath("Value") });
        checkbox.SetBinding(ArchfabCheckBox.TagProperty, new System.Windows.Data.Binding() { Path = new System.Windows.PropertyPath("Tag") });
        checkbox.SetBinding(ArchfabCheckBox.IsCheckedProperty, new System.Windows.Data.Binding() { Path = new System.Windows.PropertyPath("local:ArchfabTreeViewItemViewHelper.IsChecked"), Mode = System.Windows.Data.BindingMode.TwoWay , UpdateSourceTrigger=System.Windows.Data.UpdateSourceTrigger.PropertyChanged});

        stackpanel.AppendChild(checkbox);
        resultTemplate.VisualTree = stackpanel;
        return resultTemplate;
    }

}

The methods which searches for checked items are recursive method call, to go up and down all the different levels in the hierarchy of the treeview

public static List<KeyValueObject> FindSelectedElements(ArchfabTreeView treeView)
    {
        List<KeyValueObject> result = new List<KeyValueObject>();
        ArchfabTreeViewItem temp = null;

        foreach (object item in treeView.ItemsSource)
        {
            try
            {
                //if this is possible, you have to go a level deeper
                temp = (ArchfabTreeViewItem)item;
                result = FindSelectedElements(result, temp);
            }
            catch {
                //if catch is thrown, we have a Kv-Object here --> now check for isChecked
                ArchfabTreeViewItemViewHelper elem = (ArchfabTreeViewItemViewHelper)item;

                if (elem != null)
                {
                    if (elem.IsChecked)
                    {
                        result.Add(new KeyValueObject(elem.Key, elem.Value));
                    }
                }
            }
        }
        return result;
    }

    internal static List<KeyValueObject> FindSelectedElements(List<KeyValueObject> listKV, ArchfabTreeViewItem treeViewItem)
    {
        List<KeyValueObject> result = listKV;
        ArchfabTreeViewItem temp = null;

        foreach (object item in treeViewItem.ItemsSource)
        {
            try
            {
                //if this is possible, you have to go a level deeper
                temp = (ArchfabTreeViewItem)item;
                result = FindSelectedElements(result, temp);
            }
            catch
            {
                //if catch is thrown, we have a Kv-Object here --> now check for isChecked
                ArchfabTreeViewItemViewHelper elem = (ArchfabTreeViewItemViewHelper)item;
                if (elem != null)
                {
                    if (elem.IsChecked == true)
                    {
                        result.Add(new KeyValueObject(elem.Key,elem.Value));
                    }
                }
            }
        }
        return result;
    }

I've allready checked out the interesting article, written by Josh Smith about treeview and checkboxes and it was helpful ... but I couldn't find a solution either http://ift.tt/2uJplSd

In the end, there isn't an exception thrown or something parallel to this but the "IsChecked"-property of my helper class has not changed for any of my selected objects :/




Aucun commentaire:

Enregistrer un commentaire