Что вы пытаетесь сделать, что требует привязки данных к свойству ActualWidth
?
Это известная проблема с Silverlight, и не существует простого обходного пути.
Одна вещь, которую можно сделать, это настроить визуальное дерево таким образом, чтобы вам не нужно было фактически устанавливать ширину прямоугольника и просто позволять ему растягиваться до соответствующего размера. Таким образом, в приведенном выше примере, если вы удалите Canvas (или измените Canvas на другую панель) и оставите HorizontalAlignment
s *1005* установленным на Stretch
, он займет всю доступную ширину (фактически Ширина сетки).
Однако в вашем конкретном случае это может оказаться невозможным, и может потребоваться установить привязку данных. Уже было установлено, что это невозможно напрямую, но с помощью прокси-объекта мы можем установить требуемую привязку. Рассмотрим этот код:
public class ActualSizePropertyProxy : FrameworkElement, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public FrameworkElement Element
{
get { return (FrameworkElement)GetValue(ElementProperty); }
set { SetValue(ElementProperty, value); }
}
public double ActualHeightValue
{
get{ return Element == null? 0: Element.ActualHeight; }
}
public double ActualWidthValue
{
get { return Element == null ? 0 : Element.ActualWidth; }
}
public static readonly DependencyProperty ElementProperty =
DependencyProperty.Register("Element", typeof(FrameworkElement), typeof(ActualSizePropertyProxy),
new PropertyMetadata(null,OnElementPropertyChanged));
private static void OnElementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ActualSizePropertyProxy)d).OnElementChanged(e);
}
private void OnElementChanged(DependencyPropertyChangedEventArgs e)
{
FrameworkElement oldElement = (FrameworkElement)e.OldValue;
FrameworkElement newElement = (FrameworkElement)e.NewValue;
newElement.SizeChanged += new SizeChangedEventHandler(Element_SizeChanged);
if (oldElement != null)
{
oldElement.SizeChanged -= new SizeChangedEventHandler(Element_SizeChanged);
}
NotifyPropChange();
}
private void Element_SizeChanged(object sender, SizeChangedEventArgs e)
{
NotifyPropChange();
}
private void NotifyPropChange()
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ActualWidthValue"));
PropertyChanged(this, new PropertyChangedEventArgs("ActualHeightValue"));
}
}
}
Мы можем использовать это в xaml следующим образом:
<Grid x:Name="LayoutRoot">
<Grid.Resources>
<c:ActualSizePropertyProxy Element="{Binding ElementName=LayoutRoot}" x:Name="proxy" />
</Grid.Resources>
<TextBlock x:Name="tb1" Text="{Binding ActualWidthValue, ElementName=proxy}" />
</Grid>
Итак, мы связываем TextBlock.Text с ActualWidthValue на прокси-объекте. Прокси-объект, в свою очередь, предоставляет ActualWidth элемента, который предоставляется другой привязкой.
Это не простое решение проблемы, но это лучшее, что я могу придумать, как привязать данные к ActualWidth.
Если вы объяснили свой сценарий немного подробнее, возможно, будет возможно найти более простое решение. Привязка данных может не требоваться вообще; Можно ли было просто установить свойство из кода в обработчике событий SizeChanged?