Silverlight - Binding Listbox ActualWidth to ListboxItem Width

2.3k Views Asked by At

I'm working on a photo gallery for Windows Phone 7 and I'm trying to get each image to take the full screen and slide horizontally. What I am doing so far is to use a listbox that I have modified to scroll horizontally but the problem is that I can't seem to find a way to bind the width and the height of the ListboxItem with the ActualWidth and ActualHeight of the Listbox itself. The reason I want to do that is that if the orientation of the phone change, the size of the photos would change as well to fit the screen.

Following is the code I've got so far (I've tried using TemplatedParent and RelativeSource but I must be doing something wrong as it doesn't work at all):

<Style x:Key="PhotoGalleryItem" TargetType="ListBoxItem">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Padding" Value="0"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Grid x:Name="ListBoxItemRoot" HorizontalAlignment="Stretch" Margin="4,0,4,0" Width="{Binding RelativeSource={RelativeSource TemplatedParent},Path=ActualWidth}">
                    <Image Source="{Binding Mode=OneWay}" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="controls:PhotoGallery">
    <Setter Property="Background" Value="Red"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="Padding" Value="0"/>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:PhotoGallery">
                <Border BorderBrush="Transparent" BorderThickness="0" >
                    <Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}">
                        <ScrollViewer x:Name="Scroller" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden" >
                                <ItemsPresenter/>
                        </ScrollViewer>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemContainerStyle" Value="{StaticResource PhotoGalleryItem}" />
</Style>

Any idea on how to achieve this result?

Thanks

2

There are 2 best solutions below

1
On

this may be similar to this question I asked before

 Add HorizontalContentAlignment="Stretch" to your ListBox. 
 That should do the trick.

I see you already have 'HCA' set with a setter, so I'm not sure exactly what's going on.

0
On

You can do it in code:

public static void bindItemWidthToListBoxWidth(FrameworkElement cell)
{
  ListBox parent = findListBoxParent(cell);
  if(parent != null)
  {
    Binding binding = new Binding();
    binding.Source = parent;
    binding.Path = new PropertyPath("ActualWidth");
    binding.Mode = BindingMode.OneWay;

    cell.SetBinding(Grid.WidthProperty, binding);
  }
}

public static ListBox findListBoxParent(DependencyObject el)
{
  ListBox retValue = findAncestor<ListBox>(el);
  return retValue;
}

public static tType findAncestor<tType>(DependencyObject el)
  where tType : DependencyObject
{
  tType retValue = null;

  DependencyObject parent = VisualTreeHelper.GetParent(el);

  if(parent != null)
  {
    if (parent is tType)
    {
      retValue = (tType)parent;
    }
    else
    {
      retValue = findAncestor<tType>(parent);
    }
  }

  return retValue;
}