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?
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();
}
来源:https://stackoverflow.com/questions/7403151/binding-issue-actualwidth-on-dynamic-filled-grid