Jason Turan
Jason Turan

Reputation: 1352

Databind DockPanel

I'm trying to databind a Dockpanel in wpf to a viewmodel collection. I'm using this in order to create a customizable form and so I will not know how many children should be in the dockpanel until runtime.

The problem that I am having is that the attached property DockStyle.Dock doesn't seem to be getting applied when I set it from within a data template. The following xaml is a simplified version of what I am doing. I would expect the first button to fill up the top portion of the screen but what really happens is that they are stacked horizontally. Even hardcoding the DockPanel.Dock property has no effect on the layout of the buttons. When I look at the Visual Tree in XAMLPad I notice that there are ContentPresenters as children of the DockPanel instead of the buttons. Do ContentPresenters get layed out differently then other elements? Is there another technique to databinding to DockPanels?

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:sys="clr-namespace:System;assembly=mscorlib" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

<Grid>
<ItemsControl >
         <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <DockPanel LastChildFill="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
       <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button DockPanel.Dock="{Binding}" Content="{Binding}"></Button>
            </DataTemplate>
       </ItemsControl.ItemTemplate>
       <sys:String>Top</sys:String>
          <sys:String>Bottom</sys:String>
       <sys:String>Left</sys:String>
       <sys:String>Right</sys:String>
<sys:String>Top</sys:String>
<sys:String>Top</sys:String>
<sys:String>Top</sys:String>
    </ItemsControl>
</Grid></Page>

Here is a picture of the rendered control in xamlpad

Upvotes: 2

Views: 3725

Answers (2)

Andy
Andy

Reputation: 30418

The reason that the items aren't docked is because the control in the DataTemplate is not a direct child of the DockPanel. I believe that the ItemsControl creates one ContentPresenter for each item, just like how a ListBox creates one ListBoxItem for each item.

You could try using the ItemContainerStyle to dock the controls. I think that any properties set on it should be set on the ContentPresenter. Something like this might work:

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <DockPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="DockPanel.Dock" Value="{Binding}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
    ...
</ItemsControl>

I'm not sure if binding a string to the Dock property will work or not, though. You might try using the values in the enum directly to see if that helps as well.

Upvotes: 8

dkozl
dkozl

Reputation: 33384

This is because your Button is wrapped by ItemsControl in ContentPresenter which does not have DockPanel.Dock set. Try setting ItemContainerStyle to something like this:

<ItemsControl.ItemContainerStyle>
    <Style TargetType="{x:Type ContentPresenter}">
        <Setter Property="DockPanel.Dock" Value="{Binding}"/>
    </Style>
</ItemsControl.ItemContainerStyle>

Upvotes: 1

Related Questions