Silverlight Listbox selectable ItemTemplate - silverlight

I have a Usercontrol that contains a ListBox (lstClients) and a ComboBox
The ListBox has 2 DataTemplates setup as Resources called "LowDetailTemplate" and "HighDetailTemplate"
I need to be able to switch between the 2 DataTemplates when I change the value in a ComboBox from "Low" to "High" and vice versa. In the SelectionChanged event of the ComboBox I'm guessing I need to change the ItemTemplate of the ListBox but I'm struggling with the code to assign the DataTemplate in code behind. My latest attempt is shown below but it fails at runtime.
lstClients.ItemTemplate = (DataTemplate)this.Resources["LowDetailTemplate"];

It would be easier to define both of the views inside the same data template and then switch which is visible by use of a simple variable. Then your combo box change would just update that simple variable and so cause the view shown for each template instance to change.

Related

Issue : ListBox hides all the stack panel and text boxes with in them, Wpf

I want to bind my textboxes in wpf xaml. That is doing perfectly but when i get textbox with his x:Name="myTextbox" in codebehind. He says
"The name 'myTextbox' does not exist in the current context"
Using WPF, you cannot access items by name if there are inside a DataTemplate, like in your case, probably. However is not a good practice to modify the template using code behind. If you want to use correctly WPF, take a look at MVVM pattern.
In your case, the ListBox should be bound to an ObservableCollection and inside the template you can bind your textbox or whatever you have to the Item object.
Don't access the textbox like this : x:Name="myTextbox"
Instead access it like myTextbox.Text = "Hello World";.

Combobox Text property not changing in user control

I have a list box that has a list of user controls. Each user control has 5 combo boxes. I want to be able to read the selected text of each combo box in each user control from the main application. However, when I change the selection in the combo box, the text property of the combo box in the user control doesn't change when I read it in the main application.
Code-behind:
radQueryParamList.Items.Add(new TCardQueryParameters());
Xaml (This is just a data template for how to display a TCardQueryParameters object):
<DataTemplate x:Key="TCardViewQueryParamDataTemplate">
<tcardqueryparam:TCardQueryParameters x:Name="TCardViewerParamUC" />
</DataTemplate>
<telerik:RadListBox Grid.Column="1" ItemTemplate="{StaticResource TCardViewQueryParamDataTemplate}" Name="radQueryParamList" VerticalAlignment="Top" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.ColumnSpan="3">
Where I loop over the list of user controls
string test = radTESTGACC.Text;//TEST combo box, Text property changes
//radQueryParamList is a listbox of user controls where TCardQueryParameters is the UC
foreach(TCardQueryParameters param in radQueryParamList.Items)
{
//Each UC has a radGACC combo box in it, and I am reading what the user
//selected for each user control here in the main app, but the text property
//never changes
String gacc = param.radGACC.Text; //Text property DOESN'T CHANGE
}
I thought that each instance of the user control would keep its own state and I would just be able to read what the user selected for that combo box, but that doesn't seem to be the case.
You have not bound the SelectedItem, SelectedValue, or SelectedIndex property of your internal ComboBox to anything so it maintains its selection.
An ItemTemplate is like a cookie cutter. It contains the definition of the object, but not the object itself. Properties specific to the object's state are lost unless they are bound to something on the DataContext behind the template.
This is important to note for two aspects.
First off, to improve performance WPF usually unloads items which are not visible, which often results in items being re-created from their template anytime they are reloaded. An example would be when you minimize an application to the taskbar, then maximize it again. This is usually better on performance and memory usage, however it does mean you have to be sure you store the state of items that were created with a Template somewhere.
And second, by default ListBoxes use something called virtualization. A simple way of explaining this would be this:
Suppose you have a ListBox of 100,000 items. In your ListBox, only 10 items can be visible at a time. WPF will render roughly 14 items (the 10 visible ones, and then a few extra for a scroll buffer so you don't see anything unusual while scrolling). When you scroll to new items, WPF just re-uses the existing items that are already rendered, and just replaces the DataContext behind those items.
As you can guess, it is far better on performance to render 14 UI items instead of 100k items.
So to answer your question, you will probably want to bind either SelectedItem, SelectedValue, or SelectedIndex of your TCardQueryParameters UserControl to a property on the DataContext (which in your case appears to be another different UserControl).
It should probably be noted that what you are essentially doing is creating a list of UserControls, assigning them to the ListBox, and then telling the ListBox that it should draw each UserControl with another separate UserControl. So although you are changing the SelectedItem in the template UserControl, that change is not being reflected to your ListBox.Items copy of the UserControl.
I'm guessing you probably don't want that, so would recommend removing your ItemTemplate completely.
Or better yet, create a new class object containing all the data for your UserControl, and adding that to your ListBox.Items. Then tell the ListBox to draw that item using a TCardQueryParameters UserControl as the ItemTemplate, like you have now.

DataGrid not showing focus for SelectedItem when ViewModel is redisplayed

PersonsViewModel has a corresponding DataTemplate with a DataGrid bound to PersonList. DataGrid.SelectedItem has two-way databinding to SelectedPerson, so that when I select a row in the view, the corresponding item from PersonList is assigned to SelectedPerson.
It works fine except for one problem: when I switch screens, say, to PersonDetailScreen, and come back, the selection focus is lost! I mean, SelectedPerson still contains its former value, but the DataGrid comes out visually unselected.
I made a test, creating a two-way databound "SelectedIndex" in viewmodel. Then, I can see the actual selection is still present in viewmodel when it comes back, the problem seems to be:
"How to focus the SelectedIndex of an ItemsControl when ViewModel's datatemplate is loaded and some "SelectedIndex" databound property in such viewmodel already contains a value?"
If you have a TwoWay Binding then you can set the DataGrid.SelectedItem value from your view model. I'm a little bit confused as to your set up though... when you say 'when I switch screens ... and come back, the selection focus is lost', it sounds a bit like you're keeping the view model alive, but not the view? I'm more used to displaying a fresh view each time, but the fix would be the same either way.
Now if this were one of my views, I'd load the data into any collections from the constructor and (internally in a base class) set the CurrentItem property that is data bound to the ListBox.SelectedItem property to the first item in the collection. You should do the same, except that instead of setting it to the first item, you'd set it to whichever item was last selected.
So the answer is just to set the SelectedItem property each time the view is displayed. However, if you're saying that the SelectedItem property is already set to the item that should be selected, you may need to set it to any other value first and then set it back to the correct item.
What are we talking about here, item selection or item focus?
If you want a visual item to get focus when a template is rendered, your best bet is to set the focus manually in your xaml's code behind, by, say, hooking a handler to your page's 'Loaded' event and setting the focus manually to your datagrid by calling on its 'Focus()' method.
I know this breaks some MVVM rules, but focus management is highly dependent on your page's visual tree, and thus cannot be properly modeled through a viewmodel, which should be as view-independent as possible.
Thanks to Sheridan's insights, I have solved the problem easier than I imagined, and somewhat unintentionally.
I had the DataGrid defined directly in a DataTemplate. When the template loaded, I BELIEVE, although I am not sure at all, that some initialization step required to pass the "SelectedItem" or "SelectedItem" value to the View was "lost".
I planned to do this re-selection manually in code behind, so what I did was to move the datagrid to some UserControl I created from scratch. But then, the very fact that the DataTemplate now instantiates a proper View (derived from UserControl) inside itself, which in turn contains the datagrid, seems to "make more notifications work", so to say, and the View displays selected row like it always should.
So, now I have this in my DataTemplate:
<DataTemplate x:Name="PersonScreenTemplate" DataType="{x:Type vm:PersonScreenViewModel}">
<vw:PersonScreenViewView/>
</DataTemplate>
That seems to be the perfect pure-WPF design pattern for ViewModel-first: a datatemplate whose content is a single usercontrol, which in turn declares and binds and handles everything.

Any ideas how to implement ComboBox to represent hierarchical data?

Does anybody saw control like this somewhere?
I need to make such control to represent hierarchical data (it should be generic very likely, i.e. data binding, templates support).
Something like combination of ComboBox and MenuItem’s.
I think I will redefine the combobox itemtemplate with some hierarchicaldatatemplate along with popup class.
Just put ComboBoxes on a form and bind the ItemsSource to the top level collection.
Then bind the DataContext of the next ComboBox to the SelectedItem of the box on the left and bind its ItemSource to the collection of items.
You know how to bind to SelectedItem?
E.G.
Column1
Public String Name
Public List Column2s
So you bind the first combox to List with he displaymemberpath = name
Then on the second combobox you bind to Column1 selecteditem with items source path of Column2s
The trick is to build up the Lists within the Lists within the Lists
All right, I made it by custom control inherited from ComboBox, custom ComboBoxItem inherited from HeaderedItemsControl and using HierarchicalDataTemplate.

How to get OnSelectionChanged ListBoxItem background change when modifying the data at the same time using a ListBox control?

I have a ListBox control with an ObservableCollection instance as the control's ItemsSource property.
Everything works fine, but when I handle the control's OnSelectionChanged, my business logic modifies the collection's data and I no longer get the ListBoxItem background change you usually get when your ListBox selection changes.
Did anyone encounter the same problem ? Any solution here ?
Thanks and best regards,
Romain
It sounds like you are losing your selected item reference when the list changes.
Bind your ListBox's SelectedItem to a property on your data context and handle selection changes there.

Resources