简体   繁体   中英

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, eg:

<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, eg:

<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 , eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM