首页 文章

绑定OnwayToSource无法按预期工作 - 有哪些替代方案?

提问于
浏览
2

我有一个业务对象 - 使用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 !!)
What alternatives do I have? 我是否必须从DependancyObject派生鱼并使我的属性DPs?
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!

3 回答

  • 3

    我正在努力做到这一点,你problem problem others others,但显然是设计上的 . 你可以't set up a binding on a read only property, even if you'只想绑定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中有一个使用转换器的解决方法 . 你可以尝试一下,但是我会在你的情况下工作,因为他们的绑定是一个自定义控件,而不是内置的框架元素 .

    Even Better

    This Solution中,Boogaart提出了一个实现,定义了一个新的附加属性(类似于DockPanel.Dock = "Top"),它允许任何元素提供其观察的宽度和高度:

    <TextBlock ...
         SizeObserver.Observe="True"
         SizeObserver.ObservedWidth="{Binding Width, Mode=OneWayToSource}"
         SizeObserver.ObservedHeight="{Binding Height, Mode=OneWayToSource}"
    

    尝试一下,看看它是否合适 .

  • 1

    如果在某种操作(即按下按钮或单击超链接)后使用这些属性,则可以通过命令的CommandParameter传入ActualWidth和Height . 否则我会建议使用触发器,例如这里提供的触发器:

    http://expressionblend.codeplex.com/wikipage?title=Behaviors%20and%20Effects&referringTitle=Documentation

    我同意,OneWayToSource绑定对只读依赖项属性不起作用似乎是违反直觉的 .

  • 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());
    

相关问题