We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

M.Katsarakis: Fill GridTreeControl dynamically after action...

I'm trying to use a GridTreeControl, bound to a collection, populated with Model objects:

public class Attachment
{        
    public int ID { get; set; }
    public string Name { get; set; }
    public int ParentID { get; set; }        
}

My View looks like:

<StackPanel>
    <syncfusion:GridTreeControl>
        <syncfusion:GridTreeControl.DataContext>
            <local:ViewModel/>
        </syncfusion:GridTreeControl.DataContext>
        <i:Interaction.Behaviors>
            <b:RequestTreeItemsBehavior/>
        </i:Interaction.Behaviors>
        <syncfusion:GridTreeControl.Columns>            
            <syncfusion:GridTreeColumn MappingName="Name"/>            
        </syncfusion:GridTreeControl.Columns>
    </syncfusion:GridTreeControl>
    <Button Content="add" Command="{Binding AddCommand}"/>
</StackPanel>

I also use behavior to request tree items from collection correctly:

public class RequestTreeItemsBehavior : Behavior<GridTreeControl>
{
    ViewModel viewModel;        
    protected override void OnAttached()
    {
        base.OnAttached();
        viewModel = this.AssociatedObject.DataContext as ViewModel;
        this.AssociatedObject.RequestTreeItems += new GridTreeRequestTreeItemsHandler(AssociatedObject_RequestTreeItems);   
    } 
    void AssociatedObject_RequestTreeItems(object sender, GridTreeRequestTreeItemsEventArgs args)
    {
        if (args.ParentItem == null)
        {
            //get the root list - get all attachments who have no parent
            args.ChildList = viewModel.AttachmentsList.Where(a => a.ParentID == -1); //get all attachments whose parentID is -1 (no parent)
        }
        else 
        {   
            Attachment att = args.ParentItem as Attachment;
            if (att != null)
            {
                //get all attachments that report to the parent attachment
                args.ChildList = viewModel.GetChildren(att.ID);
            }
        }
    }        
    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.RequestTreeItems -= new GridTreeRequestTreeItemsHandler(AssociatedObject_RequestTreeItems);
    }
}

And I populate my collection in ViewModel constructor:

public class ViewModel : NotificationObject
{

    private ICommand addCommand;
    public ICommand AddCommand
    {
        get
        {
            if (addCommand == null)
                addCommand = new RelayCommand(param => OnAddCommand());
            return addCommand;
        }
    }
    private void OnAddCommand()
    {
        AttachmentsList.Add(new Attachment { ID = 10, Name = "2SUBSUB", ParentID = 4 });
        RaisePropertyChanged("AttachmentsList");
    }
    public ObservableCollection<Attachment> AttachmentsList { get; set; }
    public ViewModel()
    {
        AttachmentsList = new ObservableCollection<Attachment>();

        Attachment Root = new Attachment { ID = 1, Name = "ROOT", ParentID = -1 };

        Attachment Sub1 = new Attachment { ID = 3, Name = "1SUB", ParentID = 1 };
        Attachment Sub2 = new Attachment { ID = 4, Name = "2SUB", ParentID = 1 };
        Attachment SubSub1 = new Attachment { ID = 5, Name = "1SUBSUB", ParentID = 4 };

        AttachmentsList.Add(Root);;
        AttachmentsList.Add(Sub1);
        AttachmentsList.Add(Sub2);
        AttachmentsList.Add(SubSub1);
    }
    public int FindID(int id) {...}
    public IEnumerable<Attachment> GetChildren(int parentID)  {...}
}

At the beginning, everything works pretty fine, but after I try to use AddCommand, my new object is added to ObservableCollection, but it's not displayed in UI, even after invocation of RaisePropertyChanged(). What should I add to my Behaviour to deal with it? Or should I bind to my collection with some different way?


7 Replies

JG Jai Ganesh S Syncfusion Team July 22, 2016 12:42 PM UTC

Hi Michael, 

We have prepared a sample to add the GridTree items at runtime by using button command and its working fine in our end. 


Could you please check the above sample? If you still faced the problem, then could you please relpicate the issue in our sample or please share more information about your query. This would be more helpful pull for us to provide the prompt solution. 

Regards, 
Jai Ganesh S 



MK Michael Katsarakis August 1, 2016 02:44 PM UTC

Hallo,
unfortunatelly most of the samples you provide they are "static".
That means you fill a treegrid in the constructor. I have tested your sample and it works just fine.
But... You fill dynamically with a command the PersonDetails with a PersonInfo{}

       PersonDetails.Add(new PersonInfo() { LastName = "Sunil", FirstName = "Pradap", MyEyeColor = "Gray", DOB = new DateTime() });

You can pass as parameter (not in sample) the attribute Childen in Model, which is an ObsevableCollection. to make this added child of a

selected person

with this attribute you make the binding:

      <syncfusion:GridTreeControl Name="treeGrid"
                                    ChildPropertyName="Children"

If i will do this i see the internaltreegrid. But everything is flat.. no parent-child entities.

This is because at the momment when i fill the bindable list to the treegid i dont know any information about the attribute children.

I thought i could iterate thru the list which makes the binding with the treegrid and with the help the functions

public int FindID(int id)

to set the Children attribute.

=========================================

If i work with RequestTreeItemsBehavior to make the binding thru the behavior:

        protected override void OnAttached()
        {
            base.OnAttached();
            viewModel = this.AssociatedObject.DataContext as ViewModel;
            this.AssociatedObject.RequestTreeItems += new GridTreeRequestTreeItemsHandler(AssociatedObject_RequestTreeItems);

my viewModel instance is allways null. this is because this function is triggered before a ViewModel instance exists.

But if i change the focus or resize the window all is ok!

I dont want to have a ungly solution to call my view from the viewmodel to refresh/update.

I have to say that i fill the binding collection to treegrid i a other class passing a reference from viewmodel.

//=======================================

So simply:

* I have a Ribbon and a Docking Manager with two Documents

*  i have a  observablecollection Displaylist in viewmodel binding to treegrid. to be displayed in the first document

* I trigger a command from Ribbon to read the data filled in Displaylist

* I fill Displaylist in a separate class. (i dont know if the just readen object is a parent or a slave.. so your sample its not really dynamically loaded)

* => treegid is shown only with col headers. No data. If i change the focus between the documents the data are there.

============================================

My propose is to  do something like the docking adapter does...

A nice example it would be something like this:

Read the subfolders of a given folder and present them as parent-child in a treegrid.

Where the mainwindow has two docking workspaces.

The treegrid docked left displaying the folder and files

and a workspace at the right displaying the content of the file.

It would be nice if you trigger the command fron a Ribbon backstage.

============================================


Regards, 

Michael Katsarakis








JG Jai Ganesh S Syncfusion Team August 2, 2016 01:38 PM UTC

Hi Michael, 
 
We have prepared a sample for dynamically add items in GridTreeControl with parent-child entities and please find the sample from the below location, 
 
 
In the above sample, the GridTreeControl loaded inside the DockingManager and add the items in grid using a Ribbon button from another class. 
 
Screen Shot: 
 
 
Regards, 
Jai Ganesh S 
 



MK Michael Katsarakis August 2, 2016 02:54 PM UTC

Hallo,

Are you kidding me?
You have replaced the button with a ribonbutton..
Where is the backstage command?
And allways your sample with random names...I dont want to know more about
Random and maths..
That is an old Sample and it does not compile

Severity

Code

Description

Project

File

Line

Suppression State

Error

The tag 'DockingManager' does not exist in XML namespace 'http://schemas.syncfusion.com/wpf'. Line 19 Position 10.

SelfRelationalDatabindingDemo_2013

C:\___Syncfusion\MySamples\GTCDemo-1566561177\GTCDemo\MainWindow.xaml

19


Have you maybe a sample without random names?
 Like:

============================================

My propose is to  do something like the docking adapter does...

A nice example it would be something like this:

Read the subfolders of a given folder and present them as parent-child in a treegrid.

Where the mainwindow has two docking workspaces.

The treegrid docked left displaying the folder and files

and a workspace at the right displaying the content of the file.

It would be nice if you trigger the command fron a Ribbon backstage.

============================================

Regards, 

Michael Katsarakis




JG Jai Ganesh S Syncfusion Team August 4, 2016 02:36 PM UTC

Hi Michael,  
 
Sorry for the inconvenience. We have modified our sample to add the records without using random names through Ribbon backstage button command in viewmodel. 
 
private void OnAddCommand(object obj) 
{ 
    var grid = (obj as GridTreeControl); 
 
    var parentItem = new EmployeeInfo() { Title = "Test", ReportsTo = -1, ID = 9 }; 
              
    var childItem1= new EmployeeInfo() { FirstName = "Jillian", LastName = "Carson", Weight = 68.00, Height = 5.4, Hike = 0.50, Department = "Production", EmpID = 1021, ID = 29, DOJ = DateTime.Parse("05-08-1949"), Rating = 3, Salary = 600000, ReportsTo = 9, Title = "Production Manager" }; 
    var childItem2 = new EmployeeInfo() { FirstName = "Shu", LastName = "Ito", Weight = 70.23, Height = 5.8, Hike = 0.62, Department = "Production", EmpID = 1022, ID = 30, DOJ = DateTime.Parse("06-01-1952"), Rating = 2, Salary = 550000, ReportsTo = 9, Title = "Production Engineer" }; 
    var childItem3 = new EmployeeInfo() { FirstName = "Stephen", LastName = "Jiang", Weight = 70.00, Height = 3.2, Hike = 0.60, Department = "Production", EmpID = 1023, ID = 31, DOJ = DateTime.Parse("06-01-1952"), Rating = 3, Salary = 450000, ReportsTo = 9, Title = "Production Engineer" }; 
 
    var gridtreenode = new GridTreeNode(0, parentItem, true, null); 
    gridtreenode.ChildNodes.Add(new GridTreeNode(1, childItem1, true, gridtreenode)); 
    gridtreenode.ChildNodes.Add(new GridTreeNode(1, childItem2, true, gridtreenode)); 
    gridtreenode.ChildNodes.Add(new GridTreeNode(1, childItem3, true, gridtreenode)); 
 
    grid.InternalGrid.Nodes.Add(gridtreenode); 
 
    grid.InternalGrid.CollapseNode(gridtreenode); 
    grid.InternalGrid.ExpandNode(gridtreenode); 
} 
 
 
In the above sample, we execute the command in BackStageCommandButton inside Ribbon control. 
 
Screen Shot: 
 
 
Regards, 
Jai Ganesh S 



MK Michael Katsarakis August 5, 2016 08:27 AM UTC

Hallo Jai,

thank you. I have notice that my problem has to do with Catel framework.
I used a catel:UserControl. Thats why the DataContext it was null.
If i use UserControl, Window or RibbonWindow Catel does not accept it.

Catel and setting usercontrol's DataContext. Syncfusion control loosing its binding.
There is a problem implementing a custom control into Catel

Im had to implement IUserControl into a custom control
https://catelproject.atlassian.net/browse/CTL-680?jql=text%20~%20%22IUserControl%22

==============
Now to your sample again... Poor! See attached picture
You have to close the ribbon tab to see the entries...
The only information i got from you sample is:
<syncfusion:BackStageCommandButton Header="Add" Label="Add"   Command="{Binding Path=DataContext.AddCommand,ElementName=treeGrid}" CommandParameter="{Binding ElementName=treeGrid}" Width="200" Height="50"/>  

Regards,
Michael Katsarakis


Attachment: RibbonAnd_Treegrid_b1eb8652.7z


JG Jai Ganesh S Syncfusion Team August 8, 2016 01:00 PM UTC

Hi Michael, 
 
You can achieve your requirement by adjust the Row Definitions and setting the Margin in GridTreeControl like below, 
 
 
 
   <Grid.RowDefinitions> 
       <RowDefinition Height="600"/> 
       <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 
 
<syncfusion:GridTreeControl Name="treeGrid" Margin="0,90,0,0"  
                                        EnableHotRowMarker="False" 
                                        EnableNodeSelection="True" 
                                        ShowRowHeader="True"  
                                        ExpandStateAtStartUp="RootNodesExpanded" 
                                        VisualStyle="Metro"/> 
 
 
Regards, 
Jai Ganesh S 


Loader.
Live Chat Icon For mobile
Up arrow icon