0

I have a categories class which has subcategories and a subcategory might have subcategory and so on. I want to create a data binding for a hierarchical tree with click command for each node.

This is my class.

public partial class ProductCategory
{
    [Key]
    public int ProductCategoryId { get; set; }
    [Required]
    public string Description { get; set; }

    #region Foreign Keys
    public ProductCategory ParentProductCategory { get; set; }
    public int? ParentProductCategoryId { get; set; }
    public ICollection<ProductCategory> ChildProductCategories { get; set; }
    #endregion
    public virtual ICollection<ProductType> ProductTypes { get; set; }
}
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Mozart
  • 2,117
  • 2
  • 20
  • 38
  • What is your question? – Fruchtzwerg Nov 29 '17 at 18:22
  • @Fruchtzwerg how do i create the binding i found similar topics but they talk about deterministic number and type of child objects. – Mozart Nov 29 '17 at 18:24
  • @Fruchtzwerg here as you can the relation is one to many, parent object is the same type as the child, so there might be a need for some recursion. – Mozart Nov 29 '17 at 18:25
  • 1
    @MozartAlkhateeb Read about `HierarchicalDataTemplate`. It is what you are looking for. – Karolis Kajenas Nov 29 '17 at 18:26
  • Whats the problem using solutions like https://stackoverflow.com/questions/1912481/wpf-treeview-hierarchicaldatatemplate-binding-to-object-with-multiple-child-co ? – Fruchtzwerg Nov 29 '17 at 18:26
  • @Karolis i'll check both suggestions. – Mozart Nov 29 '17 at 18:28
  • Create `HierarchicalDataTemplate` for both, `ProductCategory` and `ProductType`, in View model create collection of `ProductCategory` and bind this list as tree source. – sTrenat Nov 29 '17 at 18:31
  • @sTrenat actually i don't care about the ProductType in this page. can you please elaborate a bit more, this is the first time i work with HierarchicalDataTemplate – Mozart Nov 29 '17 at 18:35
  • Create list to bind in your VM, e.g ObservableCollection with your first layer data, bind to it. Then in your TreeView.Resources, add HierarchicalDataTemplate, when targetType is ProductType, and bind it to `ProductTypes` proprety. That's all – sTrenat Nov 29 '17 at 18:38
  • Oh, you want just ProductCategory, my mistake :d I'm not sure if you can do treeView with just one property inside, isntead of list. But you could always make, instead of ParentProductCategory, list of subcategories. then, same as i wrote in upper comment. Damn, i'm blind xD You already have childs, so it's like i said in first comment :d – sTrenat Nov 29 '17 at 18:42
  • @sTrenat yes i want to display child categories, the child-child-categories and so on, i'll try that out anw. – Mozart Nov 29 '17 at 18:43

1 Answers1

0

This is how i solved my problem...

Code Behind (View Model)

public class ProductCategoryViewModel : ViewModelBase
{
    private ObservableCollection<ProductCategory> _productCategories;

    public ObservableCollection<ProductCategory> ProductCategories
    {
        get => _productCategories;
        set => Set(ref _productCategories, value);
    }
    public RelayCommand<string> ClickCategoryCommand { get; set; }

    public ProductCategoryViewModel()
    {
        _productCategories = new ObservableCollection<ProductCategory>();
        var p1 = new ProductCategory()
        {
            Description = "P1",
            ChildProductCategories = new List<ProductCategory>()
            {
                new ProductCategory()
                {
                    Description = "C1",
                    ChildProductCategories = new List<ProductCategory>()
                    {
                        new ProductCategory()
                        {
                            Description = "C1 C1"
                        },
                        new ProductCategory()
                        {
                            Description = "C1 C2"
                        }
                    }
                },
                new ProductCategory()
                {
                    Description = "C2"
                }
            }
        };
        _productCategories.Add(p1);
        ClickCategoryCommand = new RelayCommand<string>(Click);
    }

    private void Click(string description)
    {
        MessageBox.Show(description);
    }
}

Xaml Code

  <TreeView ItemsSource="{Binding ProductCategories}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:ProductCategory}" ItemsSource="{Binding ChildProductCategories}">
                <Button Content="{Binding Path=Description}" 
                           Command="{Binding DataContext.ClickCategoryCommand, RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}"
                        CommandParameter="{Binding Description}"/>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
Mozart
  • 2,117
  • 2
  • 20
  • 38