绑定到 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>
In a Silverlight 3.0 application I'm attempting to create a rectangle in a canvas and have it stretch the whole width of the canvas. I have attempted to do this by binding to the ActualWidth
property of a parent container (seem sample below), however while I don't see any binding errors the value is not being bound. The rectangle is not visible as its width is zero. In addition tried binding to the ActualWidth
of the canvas that contains my rectangle but this made no difference.
I did find this bug logged on Microsoft Connect but there were no workarounds listed.
Has anyone been able to solve this issue or can they point to solution?
Edit: The original code sample was not accurate of what I'm trying to achieve, updated for more clarity.
<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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您想要做什么需要您将数据绑定到 ActualWidth 属性?
这是 Silverlight 的一个已知问题,没有简单的解决方法。
可以做的一件事是以这样一种方式设置可视化树:您不需要实际设置矩形的宽度,而只需让它拉伸到适当的大小。因此,在上面的示例中,如果删除 Canvas(或将 Canvas 更改为其他面板)并将
Rectangle
的HorizontalAlignment
设置为Stretch,它将占用所有可用宽度(实际上是网格的宽度)。
但是,在您的特定情况下这可能是不可能的,并且可能确实需要设置数据绑定。已经确定这是不可能直接实现的,但是在代理对象的帮助下,我们可以设置所需的绑定。考虑以下代码:
我们可以在 xaml 中使用它,如下所示:
因此,我们将 TextBlock.Text 绑定到代理对象上的 ActualWidthValue。代理对象又提供元素的实际宽度,该宽度由另一个绑定提供。
这不是问题的简单解决方案,但这是我能想到的关于如何将数据绑定到 ActualWidth 的最佳解决方案。
如果您进一步解释一下您的场景,可能会想出一个更简单的解决方案。可能根本不需要数据绑定;是否可以仅从 SizeChanged 事件处理程序中的代码设置属性?
What are you trying to do that requires you to databind to the
ActualWidth
property?This is a known issue with Silverlight, and there is no simple workaround.
One thing that could be done is to set up the visual tree in such a way that you do not need to actually set the Width of the Rectangle, and just allow it to stretch to the appropriate size. So in the example above, if you remove the Canvas (or change the Canvas to some other Panel) and leave the
Rectangle
'sHorizontalAlignment
set toStretch
, it will take up all of the available width (effectively the Width of the Grid).However, this may not be possible in your particular case, and it may really be necessary to set up the databinding. It has already been established that this is not possible directly, but with the help of a proxy object, we can set up the required binding. Consider this code:
We can use this in xaml as follows:
So we are Binding TextBlock.Text to the ActualWidthValue on the proxy object. The proxy object in turn provides the ActualWidth of the Element, which is provided by another Binding.
This is not a simple solution to the problem, but it is the best that I can think of for how to databind to ActualWidth.
If you explained your scenario a bit more, it may be possible to come up with a simpler solution. DataBinding may not be required at all; would it be possible to just set the property from code in a SizeChanged event handler?
使用附加属性机制,可以定义表示
ActualHeight
和ActualWidth
并由SizeChanged
事件更新的属性。它的用法如下所示。技术详细信息可在以下位置找到:
http:// /darutk-oboegaki.blogspot.com/2011/07/binding-actualheight-and-actualwidth.html
与其他解决方案相比,此解决方案的优点在于解决方案中定义的附加属性(SizeChange.ActualHeight 和 SizeChange) .ActualWidth) 可用于任何 FrameworkElement,无需创建任何子类。 此解决方案可重复使用且侵入性较小。
如果链接变得过时,这里是链接上显示的 SizeChange 类:
Using the mechanism of attached properties, properties which represent
ActualHeight
andActualWidth
and are updated bySizeChanged
event can be defined. Its usage will look like the following.Technical details can be found at the following:
http://darutk-oboegaki.blogspot.com/2011/07/binding-actualheight-and-actualwidth.html
The advantage of this solution compared to others is in that the attached properties defined in the solution (SizeChange.ActualHeight and SizeChange.ActualWidth) can be used for any FrameworkElement without creating any sub class. This solution is reusable and less invasive.
In the event that the link becomes stale, here is the SizeChange Class as shown on the link:
我的解决方案是声明我自己的名为 RealWidth 的
DependencyProperty
并在SizeChanged
事件上更新其值。然后,您可以绑定到 RealWidth,它将更新,这与ActualWidth
属性不同。My solution is to declare my own
DependencyProperty
called RealWidth and update its value on theSizeChanged
event. You can then bind to RealWidth, which will update, unlike theActualWidth
property.为什么不创建一个继承自
ContentPresenter
并且实际上可以提供当前大小的简单面板控件。然后它应该用作实际内容的包装。
对我来说很有魅力而且看起来很干净。
Why not create a simple panel control that inherits from
ContentPresenter
and actually can provide the current size.It should then be used as wrapper for the actual content.
Worked for me like a charm and looks clean.
基于@darutk的答案,这里有一个附加的基于属性的解决方案,它可以非常优雅地完成这项工作。
像这样使用它:
Based on @darutk's answer, here's an attached property-based solution which does the job very elegantly.
Use it like this:
我已经测试了您使用 TestConverter 发布的更新的 xaml,以查看传递给宽度的值,它对我有用(我正在使用 VS 2010 B2)。要使用 TestConverter,只需在 Convert 方法中设置断点。
传入的值为 150,矩形的宽度为 150。
您是否期望有所不同?
I've tested the updated xaml that you publishing using a TestConverter to see what value gets passed to the width and it is working for me (I am using VS 2010 B2). To use the TestConverter just set a breakpoint in the Convert method.
A value of 150 was passed in and the Rectangle had a width of 150.
Were you expecting something different?
这是一个作为旁白的答案,可能会帮助某人绑定到
ActualWidth
。我的流程不需要更改事件,它需要当前状态值的最终结果。因此,我在自定义控件/进程上创建了一个名为
Target
的依赖属性作为FrameworkElement
,并且使用者 xaml 将绑定到相关的实际对象。当需要计算时,代码可以提取实际对象并从中提取它的
ActualWidth
。This is an as an aside answer which may help someone for binding to the
ActualWidth
.My process didn't need a change event, it needed an end result of a value in its current state. So I created a dependency property called
Target
on my custom control/process as aFrameworkElement
and the consumer xaml would bind to the actual object in question.When it was time for the calculation the code could pulled the actual object and extracted it's
ActualWidth
from it.根据 KeithMahoney 的回答,它在我的 UWP 应用程序上运行良好并解决了我的问题。但是,我在设计时看不到我的控件,因为设计时未提供 ActualWidthValue 和 ActualHeightValue 的初始值。虽然它在运行时工作得很好,但对于设计我的控件的布局来说很不方便。只要稍微修改一下,这个问题就可以解决。
在属性 ActualWidthValue 和 ActualHeightValue 的 C# 代码中,添加
<块引用>
设置{;}
让我们可以从 XAML 代码提供虚拟值。虽然它对运行时没有用处,但可以用于设计时。
在其 XAML 代码的Resources声明中,为ActualWidthValue和ActualHeightValue提供c:ActualSizePropertyProxy合适的值> 比如
<块引用>
ActualHeightValue="800" ActualWidthValue="400"
然后它会在设计时向您显示一个 400x800 的控件。
Based on KeithMahoney's answer, it works fine on my UWP App and solves my problem. However, I cannot see my control in Design time because both the initial values of ActualWidthValue and ActualHeightValue are not provided in Design time. Although it works fine in running time, it is inconvenient for designing the layout of my control. With a little modification, this problem can be solved.
In his c# code for both properties ActualWidthValue and ActualHeightValue, add
to let us can provide dummy values from XAML code. Although it is no use for running time, it can be used for design time.
In the declaration of Resources of his XAML code, provide c:ActualSizePropertyProxy suitable values for ActualWidthValue and ActualHeightValue such as
Then it will show you a 400x800 control in design time.