views:

48

answers:

2

I did quite a bit of WPF a couple of years ago but seem to have forgotten everything.

Suppose I have a simple business class, say a TFS workitem.

public class WorkItem
{
    public WorkItem(string name, DateTime date)
    {
        Name = name;
        Date = date;
    }

    public string Name { get; set; }
    public DateTime Date { get; set; }
}

Then I have a list of WorkItems, perhaps something like this.

class WiList : ObservableCollection<WorkItem>
{
    public WiList () : base()
    {
        Add(new WorkItem("1", DateTime.Now));
        Add(new WorkItem("2", DateTime.Now));
    }
}

Then I have a UserControl that represents a WorkItem, something like this.

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    x:Class="WrapPanelItemsControlTest.WorkItemControl"
    x:Name="UserControl"
    d:DesignWidth="640" d:DesignHeight="480" HorizontalAlignment="Left"
    VerticalAlignment="Top" Width="72" Height="40">

<StackPanel x:Name="LayoutRoot">
    <TextBlock x:Name="Name"/>
    <TextBlock x:Name="Date"/>
</StackPanel>

The main window contains a WrapPanel to hold the UserControls. My question is, how do I create a WrapPanel that binds to the WiList and displays the WorkItems? I remember doing something like this before, but for the death of me I can't remember how (probably something from Bea Costa's blog). Of course I can't find my old test code anywhere and seem to be expectionally bad at googling for examples.

Any help is appreaciated.

A: 

First you'll need to bind an instance of your WiList class to a ItemsControl's ItemsSource and then apply a DataTemplate for your WorkItem.

There's a similar thread here.

You can find out more about the ItemsControl's ItemsPanel here.

micahtan
+2  A: 

You probably need to use ItemsControl for this. WrapPanel can be used as layout panel for the elements of the collection. And if you only need the UserControl to show properties of one object, then the better choice would be to use a DataTemplate. Here's some XAML:

<Window.Resources>

    <DataTemplate x:Key="WorkItemTemplate" DataType="{x:Type local:WorkItem}">
        <StackPanel>
            <TextBlock Text="{Binding Name}"/>
            <TextBlock Text="{Binding Date}"/>
        </StackPanel>
    </DataTemplate>

</Window.Resources>

<Grid>

    <ItemsControl
        x:Name="itemsList"
        ItemTemplate="{StaticResource WorkItemTemplate}"
        >
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

</Grid>

And in code-behind bind the ItemsControl to the collection:

itemsList.ItemsSource = new WIList(); // or wherever the collection comes from

P.S. Initializing ItemsSource and generally accessing controls from code-behind to bind them to data is not a good practice. You would need a ViewModel (Presenter) class as the DataContext of your window. If you consider staying for some time with WPF my advice is - try to use MVVM.

P.P.S. Don't forget to implement INotifyPropertyChanged on WorkItem if you need WPF to keep up with changes of properties' values.

arconaut
Initializing ItemsSource _from code-behind_ is not a good practice. You probably meant that, but it may not be clear from the P.S.+1 =)
Yacoder
thanks! sure, i dropped those words, i'll correct myself
arconaut