我有一个业务对象 - 使用DataTemplate将其称为Fish(不是从任何东西派生,即不是DependancyObject)。否则在代码中我需要通过对Fish的引用来了解Fish DataTemplate的TextBlock部分的渲染宽度。没问题,我想。我在Fish类中添加了width和height属性,在我的数据模板中,我使用Mode = OnwayToSource将TextBlock的宽度/高度绑定到这些属性。
问题:设置Fish.width / heigh属性时,Width / Height总是NaN。我试过这个解决方法:
OneWayToSource Binding seems broken in .NET 4.0
但它也不起作用(值总是NaN)
我无法绑定到ActualWidth / ActualHeight,因为它们是只读的(为什么我不能在readonly属性上绑定OnwayToSource !!)
我有哪些替代方案?我是否必须从DependancyObject派生Fish并将我的属性设为DP?
XAML:
<DataTemplate DataType="{x:Type p:Fish}">
<Border BorderBrush="Black" BorderThickness="2" >
<TextBlock FontSize="14" TextAlignment="Center" VerticalAlignment="Center"
Width="{Binding Path=width, Mode=OneWayToSource}"
Height="{Binding Path=height, Mode=OneWayToSource}" ...
代码:
class Fish {
public double width { get; set; } // From DataTemplate TextBlock.Width.
public double height { get; set; } // From DataTemplate TextBlock.Height
}
...
double rendered_width = my_fish.width; // Use the rendered width!
答案 0 :(得分:3)
我终于意识到你要做的事情,你说得对,它是正确的。但是,WPF不同意。我发现它是problem others had before,但显然是设计上的。即使您只想绑定OneWayToSource,也无法在只读属性上设置绑定。
这是一个同样问题的问题:OneWayToSource binding from readonly property in XAML他们的解决方法是在xaml元素周围放置一个容器(具有读/写宽度/高度),并在该容器上设置绑定。这可能适合你。
在Microsoft Connect上有一个与此相关的未解决的问题,声称它是按设计行为:http://connect.microsoft.com/VisualStudio/feedback/details/540833/onewaytosource-binding-from-a-readonly-dependency-property。有人声称使用转换器的related thread中有一种解决方法。您可以尝试一下,但我不确定它是否适用于您的情况,因为它们的绑定是自定义控件,而不是内置框架元素。
更好
在This Solution中,Boogaart提出了一个定义新附加属性的实现(类似于DockPanel.Dock =“Top”),它允许任何元素提供其宽度和高度以供观察:
<TextBlock ...
SizeObserver.Observe="True"
SizeObserver.ObservedWidth="{Binding Width, Mode=OneWayToSource}"
SizeObserver.ObservedHeight="{Binding Height, Mode=OneWayToSource}"
尝试一下,看看它是否合适。
答案 1 :(得分:1)
如果在某种操作后使用这些属性,即按下按钮或单击超链接,则可以通过命令的CommandParameter传入ActualWidth和Height。否则我建议使用触发器,例如这里提供的触发器:
我同意OneWayToSource绑定对只读依赖项属性不起作用似乎是违反直觉的。
答案 2 :(得分:1)
尝试绑定OneWay。我认为OneWayToSource意味着要写入源代码。
http://msdn.microsoft.com/en-us/library/system.windows.data.bindingmode.aspx
我做了一个测试,确定Width = NaN,直到宽度为Assigned(set)。我明白这不是你想要的行为。试试这个。在指定宽度的情况下,报告(作为200)。如果未指定宽度,则报告为NaN。但ActualWidth是正确的。 ActualWidth就在那里,但显然你试图让它无法工作。
<StackPanel Orientation="Vertical">
<Border BorderThickness="1" BorderBrush="Red">
<TextBlock Name="tbwidthA" Text="{Binding Path=Howdy}" HorizontalAlignment="Left" Width="200"/>
</Border>
<TextBlock Name="tbwidthAw" Text="{Binding ElementName=tbwidthA, Path=Width}" HorizontalAlignment="Left"/>
<TextBlock Name="tbwidthAaw" Text="{Binding ElementName=tbwidthA, Path=ActualWidth}" HorizontalAlignment="Left" />
<Border BorderThickness="1" BorderBrush="Red">
<TextBlock Name="tbwidthB" Text="{Binding Path=Howdy}" HorizontalAlignment="Left" />
</Border>
<TextBlock Name="tbwidthBw" Text="{Binding ElementName=tbwidthB, Path=Width}" HorizontalAlignment="Left" />
<TextBlock Name="tbwidthAbw" Text="{Binding ElementName=tbwidthB, Path=ActualWidth}" HorizontalAlignment="Left" />
<Button Content="TBwidth" Click="Button_Click_1" Width="60" HorizontalAlignment="Left" />
</StackPanel>
有趣的是Button确实报告了正确的ActualWidth但宽度是NaN。
Debug.WriteLine(tbwidthB.Width.ToString());
Debug.WriteLine(tbwidthB.ActualWidth.ToString());