Что вы пытаетесь сделать, это требует от вас привязки к ActualWidth
? Это известная проблема с Silverlight, и нет простого обходного пути.
Одна вещь, которую можно сделать, это настроить визуальное дерево таким образом, чтобы вам не нужно было устанавливать ширину прямоугольника и просто разрешать растягиваться до соответствующего размера. Итак, в приведенном выше примере, если вы удалите Canvas (или измените Canvas на какую-либо другую панель) и оставьте , установленный на 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>
Таким образом, мы Binding TextBlock.Text к ActualWidthValue прокси-объекта. Объект-посредник, в свою очередь, предоставляет ActualWidth элемента, который предоставляется другим Binding.
Это не просто решение проблемы, но это лучшее, что я могу придумать для привязки данных к ActualWidth.
Если вы объяснили свой сценарий немного больше, может возникнуть проблема с более простым решением. DataBinding может не потребоваться вообще; можно ли просто установить свойство из кода в обработчик события SizeChanged?
Я использовал подход, предложенный с помощью обработчика события SizeChanged, и я получаю желаемый эффект.Чтобы объяснить сценарий немного больше, мне нужно было привязать к свойству ActualWidth, поскольку у меня есть бит нечетного дизайна пользовательского интерфейса, который требует, чтобы некоторые элементы отображались вне границ элемента управления. –
Более 5 лет и по-прежнему работает под WinRT ;-) - с одним небольшим изменением: новый SizeEventHandler (Element_SizeChanged) должен быть заменен непосредственно Element_SizeChanged. – TheEye