Hello, I have a XamDataTree defined as follows:
<ig:XamDataTree x:Name="_MenuTree" ItemsSource="{Binding Menus}" SelectedDataItems="{Binding SelectedMenuItems}" NodeLineVisibility="Visible" IsExpandedMemberPath="IsExpanded" NodeCheckedChanged="TreeNodeCheckedChanged"> <ig:XamDataTree.CheckBoxSettings> <ig:CheckBoxSettings CheckBoxVisibility="Visible" CheckBoxMode="Auto" /> </ig:XamDataTree.CheckBoxSettings> <ig:XamDataTree.SelectionSettings> <ig:TreeSelectionSettings NodeSelection="Multiple" /> </ig:XamDataTree.SelectionSettings> <ig:XamDataTree.GlobalNodeLayouts> <ig:NodeLayout Key="MenuLayout" TargetTypeName="clsMenuItem" DisplayMemberPath="Description" CheckBoxMemberPath="IsSelected"> </ig:NodeLayout> </ig:XamDataTree.GlobalNodeLayouts> </ig:XamDataTree>
The Menus property is in the ViewModel and is an ObservableCollection of clsMenuItem. clsMenuItem has the following properties: ID (int), Description (string) and ChildItems (ObservableCollection(of clsMenuItem))
I looked at one of the other similar posts on the forums board, but in my case, I don't see anything on the screen when then form loads, even though the Menus property has proper stuff in it.
What am I missing / doing wrong?
Hello Manasi,
Your code appears to be correct, unless there is some sort of issue with data context not being propagated down to the tree, I don’t see any issue with this. I created a sample using the description of your data and your XAML and the tree appeared as expected. Please review the sample and see if you notice may differences which may attribute to your issue.
Let me know if you have any questions.
Sincerely
Valerie
Software Developer
Infragistics Inc
hi Valerie, apparently the ItemSource was being filled after the controls were loaded. I just assigned the "Menus" property in Form Loaded event and it worked fine. Now I have another question:
1) When the form loads, if there are only some child nodes checked and others unchecked, the parent node does not show the "-" (partially selected). But if I check / uncheck on the form, then the sign shows up. Is there something I have to do in the code-behind to show the right states of all check-boxes when the form loads?
2) Can I show Green Check and Red Cross images when the user checks / unchecks something on the form? How can I assign image property to a node depending on whether it is checked or unchecked?
Thanks,
Manasi
PS: I tried to add an image here, didn't show up??
I have been looking over the sample project that you have sent, and currently, it appears that the reason that the sample isn't working correctly is because the DataContext of the window and its containing elements is not set. It also appears that the namespace definitions in a couple of the classes is incorrect as well. From my perspective, it looks like what you were looking to create was a direct VB.NET modeling of the C# project that Valerie sent, and so I have attached a working VB.NET example of the sample Valerie created to this post. You should see that in this sample project, since the data context has been corrected, the "RaiseEventPropertyChanged" part of the clsMenuItem class does get fired for the properties that change in the XamDataTree.
Regarding your most recent question, you will need to do a recursive search to include the parent hierarchy in the ItemsSource of the secondary XamDataTree. The secondary XamDataTree cannot include the hierarchy from the first tree by only having the child node in its collection. You may also need to include a separate node layout for your secondary tree, but I'm not entirely sure on this at the moment. I am going to continue looking into this, and I will update the sample that is attached to this post when I have more information for you on this matter.
Please let me know if you have any other questions or concerns on this matter.
Sincerely,AndrewAssociate DeveloperInfragistics Inc.www.infragistics.com/support
Hi Andrew, thanks for setting me right. I just ran the sample you sent and from the code behind, a lot of things are clear now. However, the SelectedMenuTree still doesn't show up. Did it work on your side? Has it something to do with any reference that I am not adding? I have attached a screenshot of the form when I ran your VBNET sample.
I am glad that the sample project I had provided you clears things up for you.
The reason that the "SelectedMenuTree" is not being populated is because although the data tree nodes in your left-hand side XamDataTree are checked, that doesn't necessarily mean that they are selected - it only means that they are "checked". You can see this by examining the SelectedMenuItems collection that you have bound to your XamDataTree.SelectedDataItems property at runtime. On load of the XamDataTree, this collection appears to be empty. If you click on one of the nodes, it will get selected, and you should see your other tree show up correctly.
If you want the checked nodes to correspond directly to the selected nodes, I would recommend that you set the IsSelectedMemberPath property of your XamDataTree's NodeLayout to the same property that your CheckBoxMemberPath is set to. This will select the nodes in your XamDataTree as long as those nodes are checked. In the case of the sample project that exists on this forum thread, the code for this would look like the following:
<ig:NodeLayout Key="MenuLayout" TargetTypeName="clsMenuItem" DisplayMemberPath="Description" CheckBoxMemberPath="IsSelected" IsSelectedMemberPath="IsSelected" >
Yep. That small changed worked fine. But if I uncheck a node, I get this exception on the RaiseEvent line in clsMenuItem:
An exception of type 'System.NullReferenceException' occurred in InfragisticsWPF4.Controls.Menus.XamDataTree.v15.2.dll but was not handled in user code
Additional information: Object reference not set to an instance of an object.
Treenode checked changed fires multiple times depending on how may levels of child are there. Please see modified sample. I have added messageboxes in the event function to see which node gets parsed first and in what order.
Is there a way to find out when the parsing is done on all nodes? I understand it is doing multiple checkedchanged event, because checking / unchecking on one node affects some other node (parent / child).
Also, if you check the root node with two levels of child, the root node is added 1 time, the level 1 parent is added 2 times and the child is added 3 times in the SelectedTree. If I can find when the parsing on all related nodes is complete, I can maybe recursively get rid of duplicate nodes?!!
I have been investigating into this issue a bit further, and I am able to reproduce the exception that you are seeing. This exception only appears in the output window on my end though, and it appears that it is handled internally. I will need a little bit more time to really look into what exactly is causing this exception, though, to see if it should be logged as a bug or not.
Regarding a way to find out when the NodeCheckedChanged event has finished on all nodes, there currently does not exist an event for this. When you check a parent node, it will check all of its child nodes, which, in turn will fire the NodeCheckedChanged event for each of these nodes. One thing that I can recommend on this matter is to add an EventSetter in your Style for XamDataTreeNodeControl for the XamDataTreeNodeControl.PreviewMouseLeftButtonDown event. This event will fire when a parent node is checked, but it will fire before the NodeCheckedChanged event fires for any other nodes. What this allows you to do is to keep a global XamDataTreeNode variable, and set it in the XamDataTreeNodeControl.PreviewMouseLeftButtonDown event. You can do this by casting the sender of that event to a XamDataTreeNodeControl element, and using the Node property of that element to get the actual node that it represents. Since this XamDataTreeNode will be globally accessible, you can then check the e.Node property of the NodeCheckedChanged event against your global XamDataTreeNode to see if they are equal. This will allow you to catch that event for the parent node that gets checked, and it appears that from debugging this, the parent-level node will be the last one to fire that particular NodeCheckedChanged event, so at the point of it firing for your parent node, you can make the assumption that all of the child nodes are checked.
Regarding the "duplicate" nodes in the "selected" XamDataTree, this behavior is expected, because you are binding your XamDataTree to the same collection as your other XamDataTree is using for its SelectedDataItems property. This, coupled with the fact that you are defining a NodeLayout for your "selected" XamDataTree allows that tree to essentially show the child nodes of each of the selected parent nodes, along with each of the items that actually exist within the SelectedDataItems collection of the original tree. That said, this behavior that you are seeing with the "duplicate" nodes is expected.
An issue gets raised here when you try to remove the "duplicate" nodes here, though. Since the collections that you are binding your "selected" XamDataTree and the SelectedDataItems property of the primary tree are the same one, if you start removing "duplicate" data items from this collection, you will affect the selected nodes in the primary tree as well as what is shown in the secondary one. To get around this, I would recommend that you define a collection separate from the primary XamDataTree to use as the "selected" one's ItemsSource. This collection can then use the NodeCheckedChanged / PreviewMouseLeftButtonDown events mentioned above to populate, or you can have it speak with the collection bound to the SelectedDataItems property of the primary XamDataTree so that only the parent-level nodes are actually added to the secondary tree.
I hope this helps you. Please let me know if you have any other questions or concerns on this matter.
That worked. Thank you.
The definition of that style for XamDataTreeNodeControl in the XamDataTree.Resources is at a lower scope than the one defined in your Grid.Resources, so yes, this will effectively override the one in your Grid.Resources. This is not to say that you can't have both, though.
I would recommend giving the style in your Grid.Resources an x:Key. This will allow you to base the one in your XamDataTree.Resources off of the one in your Grid.Resources by using BasedOn="{StaticResource gridResourceKey}" in the <Style> tag. Note, though, that this will now remove the style from your secondary XamDataTree, as the style in the Grid.Resources will no longer be implicit. You can reapply this style to your secondary XamDataTree by setting the NodeStyle property of your NodeLayout in the secondary tree to "{StaticResource gridResourceKey}." This will allow you to have both the PreviewMouse event and the context menu on the tree that you need it on.
Hi Andrew,
I can now run the selection functionality fine. But if I add the following code to the first Tree's XAML, the PreviewMouseButtonDown event stops working.
<ig:XamDataTree.Resources> <Style TargetType="{x:Type ig:XamDataTreeNodeControl}"> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu Tag="{Binding Node}"> <MenuItem Header="Remove" /> </ContextMenu> </Setter.Value> </Setter> </Style> </ig:XamDataTree.Resources>
I think this code overrides the Grid.Resources?
Can I have the PreviewMouse event and also the context menu? I need them both in my project.
Thanks
I have taken a look at the sample project that you have attached, and the issue here is not so much the PreviewMouseLeftButtonDown event or the NodeCheckedChanged event. The reason your checkboxes are not changing their state is because you are showing a message box on the PreviewMouseLeftButtonDown event. This message box will essentially demand focus, and since the "PreviewMouse" related events actually happen before the actual mouse events, the mouse action never gets triggered, and so the node never gets checked.
After removing these message boxes from your sample, I see that the NodeCheckedChanged event now gets fired, but there is still an issue. Currently, the "SelectedCopy" collection that you are using for your separate tree is getting populated inside of the setter for the bound object array used for the first tree's SelectedDataItems property. This is going to cause issues, because you will be adding more and more nodes to the tree each time this SelectedDataItems array changes. Currently, you are also adding all of the nodes that exist in the SelectedDataItems collection, so you are getting essentially the same behavior as before, but since you are adding them each time this array changes, you will actually end up with many more nodes in your separate tree than you originally had by binding the separate one to the SelectedDataItems array of the original tree.
It appears to me that perhaps you are slightly confused on what I had meant by usage of the PreviewMouseLeftButtonDown and NodeCheckedChanged events from a couple of posts ago. In an attempt to alleviate that possible confusion, I have created a sample project that is based on the one you have sent me. Note, this sample project is very barebones, in that I have removed all of the styling and anything extra that doesn't pertain to the actual selection-based operations between the two trees. This was intentional, as the point of this sample project is to demonstrate what I had tried to describe from a couple of posts to this forum ago, without the inclusion of the extra styling clutter in the code used.
The sample project demonstrating these operations is attached. I hope it helps you.
I modified the sample with the changes suggested by you, but I still think I am doing it wrong. Especially with the PreviewMouseLeftButtonDown event. If I click on a checkbox, it fires the event, but does not change the checkbox state (doesn't fire the checkedchanged event).
Can you look at the sample and let me know?