How can I use data binding in WPF to create a new user control for each element in a list?
I have a list of objects. For each item in the list, I want to create a new user control bound to that item. From what I've read, doing this programmatically is bad practice with WPF (as well as less than straightforward), so I should use data binding as a solution instead. The problem is, I can't figure out how to do this. I don't know the contents of the list (just the type) at compile-time, so I can't create and bind with XAML for each element. Google and MSDN don't seem to have any answers, so maybe I'm thinking about this the wrong way? What do I need to do?
Thanks
EDIT: To clarify, I'm trying to make my own music scoring software, something like Rosegarden. The list would contain all of the 开发者_开发知识库measures, and the usercontrols would be their visual representation.
A more generic approach than Julien Lebosquain's suggestion (and one that will work when the list of items contains objects of more than one data type):
Create a DataTemplate
to be used in presenting an item of the type(s) in your list, e.g.:
<DataTemplate DataType="local:Measure">
<local:MeasureUserControl DataContext="{Binding}"/>
</DataTemplate>
Use an ItemsControl
to present the items:
<ItemsControl ItemsSource="{Binding MeasureList}"/>
You can set the ItemsPanel
property of the ItemsControl
to an ItemsPanelTemplate
to govern how it will lay out the user controls, e.g.:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
This approach is generally preferable to using a ListBox
when you don't want the features of the ListBox
, e.g. its default border and selection behavior.
You can use a standard ListBox
with a custom item style:
Somewhere in the resources:
<Style TargetType="{x:Type ListBoxItem}" x:Key="CustomItemStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<yourns:YourControl />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In your window/page/usercontrol:
<ListBox ItemsSource="{Binding ...}" ItemContainerStyle="{StaticResource CustomItemStyle}" />
Since your objects will be bound to the listbox, an implicit ListBoxItem
will be created for each object, with its DataContext
set to the object so you can use bindings in YourControl
without any worries.
All the above answers work, but I'll leave with how I'm doing this in my application.
I'm implementing the MVVM architecture that takes advantage of these WPF features.
This is a UserControl
I'm using that has an ItemsControl
populated with the items of a certain type:
<UserControl x:Class="Controls.StepView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:Controls"
Background="Transparent">
<UserControl.Resources>
<DataTemplate DataType="{x:Type my:ParameterViewModel}" >
<my:ParameterView HorizontalAlignment="Stretch" Margin="25 0 0 0"/>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ItemsControl Name="stkStepContent" ItemsSource="{Binding Parameters}" />
</Grid>
</UserControl>
Let me explain the code for you. in the DataTemplate
section I say that I want to render objects of class ParameterViewModel with the UserControl
ParameterView. The ItemsSource
property of my ItemsControl
is binded to a List<ParameterViewModel>
. When the ItemsControl
is initiated for each ParameterViewModel on the List it will create a ParameterView and set its DataContext to the ParameterViewmodel it is rendering.
I found that this architectural pattern is the most intuitive for me to build WPF applications.
精彩评论