c# - Problema de enlace ActualWidth en Grid lleno dinámico
wpf xaml (1)
Considere el siguiente código simple:
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"/>
El evento MouseDoubleClick
:
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);
}
}
Mi etiqueta contiene la propiedad ActualWidth
de la segunda columna a través de un enlace. En Visual Studio, veo mi etiqueta que contiene el valor 316, por lo que el enlace funciona.
Al hacer doble clic en la etiqueta se desencadena su evento y se agrega una fila adicional a la cuadrícula, todas con una longitud aleatoria.
Espero ver un nuevo valor en mi etiqueta, pero (el tiempo de ejecución calculado) 0 no cambia!
¿Que me estoy perdiendo aqui?
El principal problema es que ActualWidth
de una ColumnDefinition
no es una Propiedad de Dependencia, ni implementa INotifyPropertyChanged
por lo que la Binding
no tiene forma de saber que el ActualWidth
de coltest ha cambiado.
Necesitarás actualizar explícitamente el Binding
Edit2: en este caso, es posible que pueda actualizar la Binding
en el evento SizeChanged
para la Grid
ya que las Columns
tienen *
ancho. Sin embargo, esto no funcionará al 100% con ancho Auto
ya que el ancho cambiará en función de los elementos en la ColumnDefinition
<Grid Name="grid"
SizeChanged="grid_SizeChanged">
<!--...-->
</Grid>
Controlador de eventos
void grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
BindingExpression be = label.GetBindingExpression(Label.ContentProperty);
be.UpdateTarget();
}
Editar: hizo algunos pequeños cambios en el Xaml. Esto actualizará el Enlace cada vez que haga doble clic en la primera 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>
Controlador de eventos
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();
}