Picking the right ItemsSource container - c#

I have a UserControl I've written to display a few properties from a custom object. There are multiple instances of these objects so I have an ObservableCollection of them so I can set them as an ItemsSource binding to a ListView. Now I can get an instance of this UserControl show up for each instance of my class in my ListView.
The problem is I don't really want the behavior of a ListView. I don't want the user to be able to select the entire UserControl. In fact, the user should be able to select individual elements in the UserControl.
I thought about just using a StackPanel to put these UserControls in, but it doesn't have an ItemesSource property. Is there an easy way to make this happen?

Replace your ListView with an ItemsControl and set the ItemTemplate to a suitable DataTemplate for your objects. You can set the ItemsPanel if you want to change how the panel lays out the items.
<ItemsControl ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource ItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
See this example

Related

Polyline Rendering

I have ItemsControl which is bound and creates multiple Polylines, one for each data item.
Currently I get "stack" like display - First Polyline at the top, below is second, below is third, and so on...
How can I make Polylines appear on the top of each other?
You need to change the ItemsPanel of your ItemsControl (which is by default a StackPanel that's why you get the "stack" like display) to another Panel which allows it's Children to be placed on each other like the Canvas or the Grid:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>

MVVM binding content control from observablecollection of views

I am attempting to populate a ScrollerViewer control with an arbitrary number of of UserControls (Views) whilst using the MVVM pattern and bindings.
I am using an ObservableCollection to maintain my View collection and I have this collection set as the datacontext for my ScrollViewer control, however, getting the views to appear in the scroll viewer has had me going round in circles for a while now.
Can someone please point me to either a suitable example, or kindly provide an example which demonstrates the functionality I am attempting to achieve here?
Many thanks,
First off, I think you want an ItemsControl, not a ScrollViewer. Once you do that, assuming that your ObservableCollection of viewmodels is called "Items":
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<uc:MyControl DataContext="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Replace the <uc:MyControl DataContext="{Binding}"/> with a reference to your UserControl.

Parent-Child inside DataTemplate

In my MainWindow, I've got a ListBox whose ItemsSource is bound to an ObservableCollection of Layout POCO objects:
<ListBox x:Name="ListBox" ItemsSource="{Binding Layouts}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Also, in the MainWindow, we define the visual representation of a Layout object using a UserControl (LayoutUserControl):
<DataTemplate DataType="{x:Type local:Layout}">
<local:LayoutUserControl />
</DataTemplate>
When we add objects to the Layouts collection, we see new LayoutUserControls populate the ListBox. This is pretty straight forward.
Now, what I'd like to do, is somehow communicate from the MainWindow to the individual LayoutUserControls. Specifically, from the MainWindow, I want to call a single method on each of the LayoutUserControls... If I attempt to iterate through the ListBox's Items collection, all I get is a reference to the Layout objects, not the LayoutUserControls. Since the LayoutUserControls are defined in a DataTemplate, I don't have a named reference to access them...
Is there a WPF construct that supports this type of interaction from parent to child controls? RoutedEvents were my first thought, but they only support child to parent (bubble) communication. Perhaps commands are the way to go?
Any help would be appreciated.
Thanks!
Yes, there is a method which you should never use, it's the ItemContainerGenerator.
You should, as you noted yourself, set up the communication differently, commands sound reasonable. Expose a command on the Layout and bind the UserControl to it. Or create an event and make the UserControl subscribe to it, then you can raise that.
In Silverlight there is an extension called GetItemsAndContainers as described in this SO question that does this but I cannot find an equivalent in WPF.
However it may still be possible as described in How can I access the ListViewItems of a WPF ListView? by using the VisualTreeHelper to get the LayoutUserControls inside the ListBox.

WPF - Bind a List<T> as the contents of a WrapPanel

Is is possible to make the contents(children) of a WrapPanel to be bound to a dependency property?
What I am thinking is having a dependency property that is of type List and then define a template for MyClass.
Then have the WrapPanel display them.
I know this is much easier done with a list box, but due to other constraints, I need to try with a WrapPanel before going to a list box.
I am using MVVM. I would prefer doing this in that pattern. If I were to break out of MVVM I could just use an event or name it and fill it at load time. I am hoping there is a binding way that is cleaner.
ItemsControl is your friend:
<ItemsControl ItemsSource="{Binding YourChildItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>

WPF ListBox not updating with the ItemsSource

I have what I believe should be simple two-way databinding in WPF setup, but the listbox (target) is not updating as the collection changes.
I'm setting this ItemsSource of the ListBox programmatically:
lstVariable_Selected.ItemsSource = m_VariableList;
And the ListBox is declared as follows:
<ListBox Margin="5" Name="lstVariable_Selected">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="1" Margin="0">
<TextBlock FontSize="25" Text="{Binding Path=Name}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When I initially set the ItemsSource, the ListBox (which is not visible at the time) gets its items set. However, if I go view the ListBox, updates seem to stop at that point.
I can then remove an item from the m_VariableList collection, and it does not disappear from the ListBox. Likewise, if I add one, it doesn't appear.
What gives?
Is your m_VariableList implementing INotifyCollectionChanged? If it's not an ObservableCollection, then changes to it's contents will not automatically be reflected in the UI.
The problem is not in the XAML that you have provided. I used the same XAML successfully in a test application; however, I was able to replicate the issue you are experiencing by re-instantiating the m_VariableList variable.
When the m_VariableList is given a new instance, or pointed to a new object, it is not reflected in the ListBox because the control has its own reference to the data. This may not be the cause of your problem, but I'd recommend looking over your code-behind to ensure that the variable is not getting re-instantiated.
i got stuck for more than hour and then simple logic solved this problem
just set itemsource to clear list and then set source u need again
lstVariable_Selected.ItemsSource = new List<Object>();
lstVariable_Selected.ItemsSource = m_VariableList;

Categories