Binding to an ObservableCollection of UserControls - silverlight

Simple Silverlight question: I have an ObservableCollection<MyObject> in my viewmodel. Every MyObject has a Label property. If I bind a ListBox to the collection and set DisplayMemberPath to Label, or set the ItemTemplate to a TextBlock that binds the Text property to Label, all works as expected.
If I change MyObject so it derives from a UserControl, the Label text no longer shows up in the ListBox; each item just shows up as a blank strip a few pixels tall. Why is this? There's obviously something I'm missing here about how different things get rendered.

The ListBox determines that the set of items in its ItemsSource are already UIElement instances and therefore decides to use those elements directly as the content of the ListBoxItem elements it creates.

Related

How Do I Change WPF Listview SelectedItem Font Color With ItemSource Bound?

I have WPF window containing a listview that has it's itemsource set to a collection of objects. When I access SelectedItem or SelectedItems[] or Items[], I get the my object back that's bound to that item, not the ListViewItem item itself. I have no idea how to select a row and change it's color since I can't access the item itself, like a winform listviewitem.
ListView derives from ItemsControl which exposes the ItemContainerGenerator property. This object allows you to map a bound entity to its ItemContainer (the item your are looking for) and back.

How can I set the keyboard focus to the content of a ContentPresenter when it changes?

I have a ContentControl in my view which is databound to the CurrentItem property of my viewmodel. The objects that are exposed via CurrentItem each has its own DataTemplate.
When the CurrentItem property changes, the appropriate DataTemplate for that item is displayed, as it should be. However, I cannot find out a way to set the keyboard focus to the content of the DataTemplate.
Even if I manually set the keyboard focus to the DataTemplate, if the CurrentItem property changes (and a new Template is instantiated) the focus is lost (FocusManager.GetFocussedElement returns null).
How can I set the keyboard focus to the content of the ContentPresenter when it changes?
I believe you can use the LayoutUpdated event on either your ContentControl or the ContentPresenter. This should fire anytime the Content/ContentTemplate/etc changes.
Alternatively, you could derive a class from ContentControl then override the OnContentChanged, OnContentTemplateChanged, etc methods. Then you'd need to search down the visual tree and set the focus. You may need to use the Dispatcher to delay the focus setting code.

WPF Accessing Items inside Listbox which has a UserControl as ItemTemplate

I have Window that has a ListBox
ListBox(MyListBox) has a DataTable for its DataContext
ListBox's ItemSource is : {Binding}
Listbox has a UserControl(MyUserControl) as DataTemplate
UserControl has RadioButtons and TextBoxes (At first They're filled with values from DataTable and then user can change them)
Window has one Submit Button
What I want to do is, when user clicks the submit button
For each ListBox Item, get the values form UserControl's TextBoxes and RadioButtons.
I was using that method for this job :
foreach(var element in MyListBox.Items)
{
var border = MyListBox.ItemContainerGenerator.ContainerFromItem(element)as FrameworkElement;
MyUserControl currentControl = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(myBorder,0) as Border,0)as ContentPresenter,0)as MyUserControl;
//And use currentControl
}
I realised nothing when using 3-5 items in Listbox. But when I used much more items, I saw that "var border" gets "null" after some elements looped in foreach function.
I found the reason here :
ListView.ItemContainerGenerator.ContainerFromItem(item) return null after 20 items
So what can I do now? I want to access all items and get their values sitting on user controls.
Thanks
You should use objects who implement INotifyPropertyChanged and bind an ObservableCollection of it to the ItemSource
And then you can get all the list of items.
Here some quick links from MSDN to get more informations
How to: Implement Property Change Notification
Binding Sources Overview
You should google for some tutorials about this.
Zied's post is a solution for this problem. But I did the following for my project:
I realised that there's no need to use UserControl as DataTemplate in my project. So I removed ListBox's DataTemplate.
I removed MyListBox.DataContext = myDataTable and used this:
foreach(DataRow dr in myDataTable.Rows)
{
MyUserControl muc = new MyUserControl(dr);
myListBox.Items.Add(muc);
}
I took DataRow in my UserControl's constructor and did what I want.
And at last I could access my UserControls in ListBox by using :
foreach(MyUserControl muc in
myListBox)
{
//do what you want
}
Easy huh? :)

How to assign value of the dataContext to ListBox control in silverlight?

Hi I have contentControl in my user control. I am applying style to this contentControl which consist of TextBlock and ListBox. I am binding text of the textBlock to CategoryName(from Tag of the control). I want to bind category's child items to listBox. I have set ContentControl's dataContext property to child items[]. Now how to bind these child items to listbox which is in resource.
In loaded event of the user control
Panel pnl = sender as Panel;
Category category = panel.Tag as Category;
Items[] items = GetChildItemsByCategoryId(category.CategoryID);
mainContent.DataContext = items;
If the control is in the visual tree of mainContent, simply set in code or XAML
ItemsSource={Binding}

How do I loop through a set of items in a databound Silverlight control such as the ListBox?

I have a silverlight ListBox that has it's ItemsSource set. From the C# code behind I want to loop through each ListBox item and change the value of the text and access controls that are in the ListBox ItemTemplate. How would I do that?
ListBox controls in silverlight are bound to an ienumerable type, so that if any value in the ListBox changes, the underlying data is changed and vice versa depending on what type of binding you require. To effectively iterate the items you'll want to iterate through the enumerable object you've bound to.
You can get to the collection by accessing the ListBox.ItemsSource property and change the text of appropriate items, perform LINQqueries etc. If you have bound the controls correctly, saving the collection should update the list.
Hope this helps!

Resources