I am wondering if there is one "global" generator for TreeView or does a new ItemContainerGenerator gets created on each node/level, when expanded?
Anyone who had to deal with this depth of wpf?
Thanks again in advance I appreciate your help much. :) :)
I posted this question to msdn forum as well. And this is what they answered to me.
I guess I was right. Each node has its own generator.
Check it out:
http://social.msdn.microsoft.com/Forums/en-US/d36d164a-296e-44d5-80a6-4f09414d0a64/does-treeview-create-a-new-itemcontainergenerator-per-nodelevel?forum=wpf
ItemContainerGenerator for any ItemsControl (including TreeView) is associated with the control and is responsible for generating the UIElement items on behalf of a ItemsControl.
ItemContainerGenerator generates each and every item, not each item creates its own ItemContainerGenerator.
But as rightly pointed out by you, treeviewitem is in itself itemscontrol so each will have its generator which will generate its child.
MSDN ref: http://msdn.microsoft.com/en-us/library/system.windows.controls.itemcontainergenerator.aspx
The ItemsControl generates its items through the
IItemContainerGenerator interface. The ItemContainerGenerator property
of the ItemsControl is of type ItemContainerGenerator, which
implements the IItemContainerGenerator interface.
Related
I have a DataTemplate defined in XAML. I want to customize it and give it to DataGridTemplateColumn.CellTemplate. But when I call LoadContent(), the VisualTree is still null, instead a UIElement tree is returned. After I customize the tree, how can I convert it back to a DataTemplate? Or is there a way to feed the DataGrid cells directly with UIElement?
I think it should help you
Code Project
I've learned that once the UI controls are instantiated, it is impossible to convert back to a DataTemplate i.e. FrameworkElementFactory tree.
I have tried to get the listbox items using VisualTreeHelper class. When I do VisualTreeHelper.GetChildrenCount((DependencyProperty)listBox1) it returns count as 0. But the listbox has lot of listboxitems in it.Can someone let me know if I am doing any mistake?
Regards,
Lalith
Have you tried to use the ItemContainerGenerator property of the Listbox class ? It has some methods you can use to retrieve Listbox items.
http://msdn.microsoft.com/en-US/library/system.windows.controls.itemscontrol.itemcontainergenerator(v=VS.95).aspx
I'm just getting started with silverlight.
Basically I have a silverlight user control that has various dataGrids and a combobox, their item sources set to the properties of a custom plain c# object.
My problem is that I have a dropdown list that when a user selects an item from the list a new row should appear in one of the grids.
All I'm doing is handling the SelectionChanged event and adding a new item to to a list in my custom object and setting the itemsource for the grid again. This doesnt seem to work; no row is added to the dataGrid
I have no idea how to force my grid to "rebind" to this property.
I've been reading about dependency properties, are these what I need?
Any pointers would be really appreciated.
The list you are binding against should be of the type ObservableCollection. Then the datagrid should display the new item automatically .
The problem is that when you assign the same List to the ItemsSource the DataGrid knows its the same List so it does nothing.
As Henrik points out you should expose an Observable<T> not a List<T> for properties that are to be bound to ItemsSource properties of multi-item controls such as DataGrid, ListBox etc.
In addition your "plain c# objects" should implement the INotifyPropertyChanged interface if you want changes made by code to these properties to automatically appear in the UI.
What you probably want to do is update the binding source - which is relatively easily done.
private void ComboBox_SelectionChanged(object sender, RoutedEventArgs e)
{
this.dataGrid.GetBindingExpression(DataGrid.ItemsSource).UpdateSource();
}
This is a tad hack-y but will do what you need it to do. Implementing INotifyPropertyChanged is another great suggestion.
Silverlight show have some great info on INotifyPropertyChanged here
It seems that others have had variations on this question, but from what I can tell it hasnt been addressed for folks using collections in a single view model.
I have a VM that contains an ObservableCollection of objects, not a VM for each object. Therefore I dont think I can use the SelectedItem bool that is often discussed because I dont think I can bind to the property on the collection's objects...just the properties on the VM.
So I've got the whole thing pretty well written with no code-behind and minimal coupling, but when a new item is added to the collection, which is bound to the treeView, I need to select that item.
Ideas?
Thanks!
When thinking about this. You should really build a wrapper for every element of the tree view that has the IsSelected bool on it as well as the IsExpanded bool they make life so much easier for displaying the data. You could even just add them to your class and use them from there.
Josh Smith has an article on CodeProject where he suggests creating a ViewModel object to represent each node of the TreeView, and then autowires them up as needed.
http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx
I created a ListBox that has a DataTemplate as Itemtemplate. However, is there an easy way to access the generated UIElement instead of the SelectedItem in codebehind?
When I access SelectedItem, I just get the selected object from my
ItemsSource collection. Is there a way to access the UIElement (ie. the
element generated from the DataTemplate together with the bound object)?
You are looking for the ItemContainerGenerator property. Each ItemsSource has an ItemContainerGenerator instance. This class has the following method that might interest you: ContainerFromItem(object instance).
Once you have a handle to the ListBoxItem, you can go ahead and browse the logical and visual tree. Check out Logical Tree Helper and Visual Tree Helper.
Like Andy said in the comments, just because the item exists in your collection doesn't mean a container has been generated for it. Any kind of virtualizing panel scenario will raise this issue; UIElements will be reused across the different items. Be careful with that as well.
siz, Andy and Bodeaker are absolutely right.
Here is how I was able to retrieve the textbox of the listbox's selected item using its handle.
var container = listboxSaveList.ItemContainerGenerator.ContainerFromItem(listboxSaveList.SelectedItem) as FrameworkElement;
if (container != null)
{
ContentPresenter queueListBoxItemCP = VisualTreeWalker.FindVisualChild<ContentPresenter>(container);
if (queueListBoxItemCP == null)
return;
DataTemplate dataTemplate = queueListBoxItemCP.ContentTemplate;
TextBox tbxTitle = (TextBox)dataTemplate.FindName("tbxTitle", queueListBoxItemCP);
tbxTitle.Focus();
}
(Note: Here, VisualTreeWalker is my own wrapper over VisualTreeHelper with various useful functions exposed)