tags:

views:

84

answers:

2

I have a WPF Window with a Canvas that is used to show a terrain map. I would like to place symbols on this map according to an IEnumerable<MapSymbolDefinition> where MapSymbolDefinition is defined as follows:

public class MapSymbolDefinition
{
  string SymbolFileName { get; set; }
  int XLocation { get; set; }
  int YLocation { get; set; }
}

All symbols are stored in the Symbols folder of my project, so the path to any symbol would be [ProjectFolder]/Symbols/SymbolFileName.bmp.

Any thoughts on how I can set this up so I don't have to populate a bunch of Image objects manually in the code-behind?

Thanks.

A: 

The WPF way: Use DataTemplates and a ListBox and converters and .... Check out this example.

The quick way: Just do it in the code-behind and call your view a control.

Ray
+2  A: 

Use an ItemsControl with customized ItemsPanel, ItemContainerStyle and ItemTemplate:

<ItemsControl ItemsSource="{Binding MapSymbols}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Canvas.Top" Value="{Binding YLocation}"/>
            <Setter Property="Canvas.Left" Value="{Binding XLocation}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type local:MapSymbolDefinition}">
            <Image Source="{Binding SymbolFileName, Converter={StaticResource ImageNameConverter}}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Update after comments: You can define an ItemTemplate to provide the visual tree for each item in the collection. In this case I used a converter to convert the SymbolFileName property to an image, but you could equally define a separate property on your MapSymbolDefinition class that yields the full path. The latter approach is more in line with MVVM best practices.

HTH, Kent

Kent Boogaart
+1, Plus the DataTemplate's which do the Image.
sixlettervariables
Hi, Kent. I just edited my question because I think was unclear about one thing: the enumeration actually contains *definitions* of map symbols (not the symbols themselves). So, in your example, the ItemsSource is not being bound to the actual Image objects I want to show. Is there some way to include a DataTemplate that converts from SymbolFileName to `<Image Source="{Path=SymbolFileName}"`? Thanks.
DanM
Or, to put it another way, what @sixlettervariables said :)
DanM
@DanThMan: that code looks perfect actually (minus not saying Binding). `<Image Source="{Binding SymbolFileName}" />` in the `DataTemplate` is all you need. The confusing part Kent handled which is having the `ItemContainerStyle` do the `Canvas` offsets.
sixlettervariables
I've updated my answer to clear up some confusion.
Kent Boogaart
@Kent, Perfect! Thanks!
DanM