2

Consider the following, simple code:


XAML:

<Grid Height="60" Name="grid">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="162*" />
        <ColumnDefinition x:Name="coltest" Width="316*" />
        <ColumnDefinition Width="239*" />
    </Grid.ColumnDefinitions>
</Grid>
<Label MouseDoubleClick="TextBox_MouseDoubleClick" 
    Content="{Binding ElementName=coltest, Path=ActualWidth}" Grid.Row="1"/>

The MouseDoubleClick event:

private void TextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    grid.RowDefinitions.Add(new RowDefinition());
    for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
    {
        Random r = new Random();
        Label l = new Label { Content = r.Next(10, 1000000000).ToString() };
        grid.Children.Add(l);
        Grid.SetRow(l, grid.RowDefinitions.Count - 1);
        Grid.SetColumn(l, i);
    }
}

My label contains the ActualWidth property of the second column via a binding. In Visual Studio I see my label containing the value 316, so the binding works.

Double clicking the label triggers its event and adds an extra row to the grid, all with a random length.

I expect to see a new value at my label, but (the at runtime calculated) 0 does not change!

What am I missing here?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
321X
  • 3,153
  • 2
  • 30
  • 42

1 Answers1

4

The main problem is that ActualWidth of a ColumnDefinition isn't a Dependency Property, nor does it implement INotifyPropertyChanged so the Binding has no way of knowing that the ActualWidth of coltest has changed.

You'll need to explicitly update the Binding

Edit2: In this case, you might be able to update the Binding in the SizeChanged event for the Grid since the Columns have * width. This won't work 100% with Auto width though since the width will change based on the elements in the ColumnDefinition

<Grid Name="grid"
      SizeChanged="grid_SizeChanged">
    <!--...-->
</Grid>

Event handler

void grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
    BindingExpression be = label.GetBindingExpression(Label.ContentProperty);
    be.UpdateTarget();
}

Edit: Made some small changes to the Xaml. This will update the Binding everytime you doubleclick the first Label

<Grid Name="grid">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="162*" />
        <ColumnDefinition x:Name="coltest" Width="316*" />
        <ColumnDefinition Width="239*" />
        <ColumnDefinition Width="239*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Label MouseDoubleClick="TextBox_MouseDoubleClick"
           Name="label"
           Content="{Binding ElementName=coltest, Path=ActualWidth}" Grid.Row="0"/>
</Grid>

Event handler

private void TextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    grid.RowDefinitions.Add(new RowDefinition());
    for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
    {
        Random r = new Random();
        Label l = new Label { Content = r.Next(10, 1000000000).ToString() };
        grid.Children.Add(l);
        Grid.SetRow(l, grid.RowDefinitions.Count - 1);
        Grid.SetColumn(l, i);
    }
    BindingExpression be = label.GetBindingExpression(Label.ContentProperty);
    be.UpdateTarget();
}
Fredrik Hedblad
  • 83,499
  • 23
  • 264
  • 266
  • Ah, I understand. How can I update the binding? It depends on when the ActualWidth property is calculated right? – 321X Sep 13 '11 at 14:21
  • Sure thing, glad I was able to help out :) – Fredrik Hedblad Sep 13 '11 at 14:40
  • I actually had to listen to the `LayoutUpdated` event. The `SizeChanged` event was only triggered at initialization. – 321X Sep 13 '11 at 19:33
  • Well, the `SizeChanged` event is raised everytime the `Grid` changes size, but if you add a new `ColumnDefinition` for example, the `Grid` size won't change but the `ColumnDefinitions` of the `Grid` will. `LayoutUpdated` is raised on every update of the layout (size change or whatnot) so yes, no chance of missing the update there:) – Fredrik Hedblad Sep 13 '11 at 20:45