Ric*_*ire 24 silverlight actualwidth
在Silverlight 3.0应用程序中,我试图在画布中创建一个矩形,并使其拉伸画布的整个宽度.我试图通过绑定到ActualWidth父容器的属性(下面的示例)来做到这一点,但是当我没有看到任何绑定错误时,该值没有被绑定.矩形不可见,因为其宽度为零.另外尝试绑定到ActualWidth包含我的矩形的画布,但这没有区别.
我确实发现Microsoft Connect上记录了此错误,但没有列出变通方法.
有没有人能够解决这个问题,还是他们可以指出解决方案?
编辑:原始代码示例不准确我想要实现的目标,更新更清晰.
<UserControl>
<Border BorderBrush="White"
BorderThickness="1"
CornerRadius="4"
HorizontalAlignment="Center">
<Grid x:Name="GridContainer">
<Rectangle Fill="Aqua"
Width="150"
Height="400" />
<Canvas>
<Rectangle Width="{Binding Path=ActualWidth, ElementName=GridContainer}"
Height="30"
Fill="Red" />
</Canvas>
<StackPanel>
<!-- other elements here -->
</StackPanel>
</Grid>
</Border>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
Kei*_*ney 31
你想要做什么,这需要你数据绑定到ActualWidth属性?这是Silverlight的一个已知问题,并没有简单的解决方法.
可以做的一件事是以这样的方式设置可视化树,使得您不需要实际设置矩形的宽度,并且只允许它伸展到适当的大小.所以在上面的例子中,如果您删除画布(或更改画布一些其他面板)和离开Rectangle的HorizontalAlignment设置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"));
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以在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>
Run Code Online (Sandbox Code Playgroud)
所以我们将TextBlock.Text绑定到代理对象的ActualWidthValue.代理对象依次提供Element的ActualWidth,它由另一个Binding提供.
这不是解决问题的简单方法,但是我能想到如何将数据绑定到ActualWidth是最好的.
如果您更多地解释了您的场景,可能会提出一个更简单的解决方案.根本不需要DataBinding; 是否可以从SizeChanged事件处理程序中的代码设置属性?
小智 21
使用的机构附加属性,其表示的属性ActualHeight和ActualWidth与由更新SizeChanged事件可被定义.它的用法如下所示.
<Grid local:SizeChange.IsEnabled="True" x:Name="grid1">...</Grid>
<TextBlock Text="{Binding ElementName=grid1,
Path=(local:SizeChange.ActualHeight)}"/>
Run Code Online (Sandbox Code Playgroud)
技术细节可在以下位置找到:
http://darutk-oboegaki.blogspot.com/2011/07/binding-actualheight-and-actualwidth.html
相比其他这种解决方案的优点是,在所述溶液(SizeChange.ActualHeight和SizeChange.ActualWidth)中定义的附加属性可用于任何FrameworkElement的而不会产生任何的子类.该解决方案可重复使用且侵入性较小.
如果链接变得陈旧,这里是SizeChange类,如链接所示:
// Declare SizeChange class as a sub class of DependencyObject
// because we need to register attached properties.
public class SizeChange : DependencyObject
{
#region Attached property "IsEnabled"
// The name of IsEnabled property.
public const string IsEnabledPropertyName = "IsEnabled";
// Register an attached property named "IsEnabled".
// Note that OnIsEnabledChanged method is called when
// the value of IsEnabled property is changed.
public static readonly DependencyProperty IsEnabledProperty
= DependencyProperty.RegisterAttached(
IsEnabledPropertyName,
typeof(bool),
typeof(SizeChange),
new PropertyMetadata(false, OnIsEnabledChanged));
// Getter of IsEnabled property. The name of this method
// should not be changed because the dependency system
// uses it.
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
// Setter of IsEnabled property. The name of this method
// should not be changed because the dependency system
// uses it.
public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
#endregion
#region Attached property "ActualHeight"
// The name of ActualHeight property.
public const string ActualHeightPropertyName = "ActualHeight";
// Register an attached property named "ActualHeight".
// The value of this property is updated When SizeChanged
// event is raised.
public static readonly DependencyProperty ActualHeightProperty
= DependencyProperty.RegisterAttached(
ActualHeightPropertyName,
typeof(double),
typeof(SizeChange),
null);
// Getter of ActualHeight property. The name of this method
// should not be changed because the dependency system
// uses it.
public static double GetActualHeight(DependencyObject obj)
{
return (double)obj.GetValue(ActualHeightProperty);
}
// Setter of ActualHeight property. The name of this method
// should not be changed because the dependency system
// uses it.
public static void SetActualHeight(DependencyObject obj, double value)
{
obj.SetValue(ActualHeightProperty, value);
}
#endregion
#region Attached property "ActualWidth"
// The name of ActualWidth property.
public const string ActualWidthPropertyName = "ActualWidth";
// Register an attached property named "ActualWidth".
// The value of this property is updated When SizeChanged
// event is raised.
public static readonly DependencyProperty ActualWidthProperty
= DependencyProperty.RegisterAttached(
ActualWidthPropertyName,
typeof(double),
typeof(SizeChange),
null);
// Getter of ActualWidth property. The name of this method
// should not be changed because the dependency system
// uses it.
public static double GetActualWidth(DependencyObject obj)
{
return (double)obj.GetValue(ActualWidthProperty);
}
// Setter of ActualWidth property. The name of this method
// should not be changed because the dependency system
// uses it.
public static void SetActualWidth(DependencyObject obj, double value)
{
obj.SetValue(ActualWidthProperty, value);
}
#endregion
// This method is called when the value of IsEnabled property
// is changed. If the new value is true, an event handler is
// added to SizeChanged event of the target element.
private static void OnIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
// The given object must be a FrameworkElement instance,
// because we add an event handler to SizeChanged event
// of it.
var element = obj as FrameworkElement;
if (element == null)
{
// The given object is not an instance of FrameworkElement,
// meaning SizeChanged event is not available. So, nothing
// can be done for the object.
return;
}
// If IsEnabled=True
if (args.NewValue != null && (bool)args.NewValue == true)
{
// Attach to the element.
Attach(element);
}
else
{
// Detach from the element.
Detach(element);
}
}
private static void Attach(FrameworkElement element)
{
// Add an event handler to SizeChanged event of the element
// to take action when actual size of the element changes.
element.SizeChanged += HandleSizeChanged;
}
private static void Detach(FrameworkElement element)
{
// Remove the event handler from the element.
element.SizeChanged -= HandleSizeChanged;
}
// An event handler invoked when SizeChanged event is raised.
private static void HandleSizeChanged(object sender, SizeChangedEventArgs args)
{
var element = sender as FrameworkElement;
if (element == null)
{
return;
}
// Get the new actual height and width.
var width = args.NewSize.Width;
var height = args.NewSize.Height;
// Update values of SizeChange.ActualHeight and
// SizeChange.ActualWidth.
SetActualWidth(element, width);
SetActualHeight(element, height);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 8
我知道的方式太晚了,但只是在努力解决这个问题.我的解决方案是声明我自己的DependencyProperty名为RealWidth并更新其在SizeChanged事件上的值.然后,您可以绑定到RealWidth,它将更新,与ActualWidth属性不同.
public MyControl()
{
InitializeComponent();
SizeChanged += HandleSizeChanged;
}
public static DependencyProperty RealWidthProperty =
DependencyProperty.Register("RealWidth", typeof (double),
typeof (MyControl),
new PropertyMetadata(500D));
public double RealWidth
{
get { return (double) GetValue(RealWidthProperty); }
set { SetValue(RealWidthProperty, value); }
}
private void HandleSizeChanged(object sender, SizeChangedEventArgs e)
{
RealWidth = e.NewSize.Width;
}
Run Code Online (Sandbox Code Playgroud)
小智 5
为什么不创建一个简单的面板控件来继承ContentPresenter并实际上可以提供当前大小.
public class SizeNotifyPanel : ContentPresenter
{
public static DependencyProperty SizeProperty =
DependencyProperty.Register("Size",
typeof (Size),
typeof (SizeNotifyPanel),
null);
public Size Size
{
get { return (Size) GetValue(SizeProperty); }
set { SetValue(SizeProperty, value); }
}
public SizeNotifyPanel()
{
SizeChanged += (s, e) => Size = e.NewSize;
}
}
Run Code Online (Sandbox Code Playgroud)
然后它应该用作实际内容的包装器.
<local:SizeNotifyPanel x:Name="Content">
<TextBlock Text="{Binding Size.Height, ElementName=Content}" />
</local:SizeNotifyPanel>
Run Code Online (Sandbox Code Playgroud)
为我工作就像一个魅力,看起来干净.
| 归档时间: |
|
| 查看次数: |
19336 次 |
| 最近记录: |