Связывание OnwayToSource не работает должным образом - какие альтернативы? - PullRequest
2 голосов
/ 26 октября 2011

Ive бизнес-объект - назовите его Fish (не полученный из чего-либо, т.е. не DependancyObject), который отображается в ListBox с использованием DataTemplate.Иначе, где в коде мне нужно знать визуализированную ширину части TextBlock шаблона Data Fish через ссылку на Fish.Нет проблем, подумал я.Я добавил свойства ширины и высоты в класс Fish и в своем шаблоне данных я привязал ширину / высоту TextBlock к ним, используя Mode = OnwayToSource.
Проблема: ширина / высота всегда равны NaN при настройке моих свойств Fish.width / heigh,Я попробовал этот обходной путь:
Привязка OneWayToSource кажется сломанной в .NET 4.0
, но она также не работает (значение всегда NaN).
Я не могу привязаться к ActualWidth / ActualHeight, потому что онитолько для чтения (почему я не могу привязать OnwayToSource к свойству только для чтения !!)
Какие у меня есть альтернативы? Нужно ли мне извлекать Fish из DependancyObject и создавать мои свойства 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!

Ответы [ 3 ]

3 голосов
/ 26 октября 2011

Я наконец понял, что ты пытаешься сделать, и ты прав, что это должно сработать. WPF, однако, не согласен. Я вижу, что это проблема , которую другие имеют имели до , но это, очевидно, было разработано. Вы не можете установить привязку для свойства только для чтения, даже если вы просто хотите связать OneWayToSource.

Вот вопрос с той же проблемой: Привязка OneWayToSource из свойства readonly в XAML Их обходной путь - поместить контейнер (имеющий ширину / высоту чтения / записи) вокруг элемента xaml и настроить привязка к этому контейнеру. Это может работать для вас.

Существует неразрешенная проблема, связанная с этим в Microsoft Connect, где заявлено, что она является поведением по своему замыслу: http://connect.microsoft.com/VisualStudio/feedback/details/540833/onewaytosource-binding-from-a-readonly-dependency-property. Кто-то требует обходного пути в потоке , который использует конвертер. Вы можете попробовать это, но я не уверен, что это сработает в вашем случае, поскольку их привязка была к пользовательскому элементу управления, а не к встроенному элементу Framework.

Еще лучше

В . В этом решении Boogaart предложила реализацию, определяющую новое присоединенное свойство (аналогично DockPanel.Dock = "Top"), которое позволяет любому элементу указывать ширину и высоту для наблюдения:

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

Попробуйте и посмотрите, подходит ли он.

1 голос
/ 26 октября 2011

Попробуйте связать OneWay.Я думаю, что OneWayToSource означает, что хочет написать в источник.

http://msdn.microsoft.com/en-us/library/system.windows.data.bindingmode.aspx

Я провел тест и достаточно уверен, что Width = NaN, пока ширина не будет присвоена (установлена).Я понимаю, что это не то поведение, которое вы хотите.Попробуй это.Где назначена ширина, сообщается (как 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, но Width равно NaN

        Debug.WriteLine(tbwidthB.Width.ToString());
        Debug.WriteLine(tbwidthB.ActualWidth.ToString());
1 голос
/ 26 октября 2011

Если вы используете эти свойства после какого-либо действия, то есть нажатия кнопки или щелчка гиперссылки, вы можете передать ActualWidth и Height через CommandParameter команды. В противном случае я бы предложил использовать триггеры, подобные тем, которые доступны здесь:

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

Я согласен, что кажется нелогичным, что привязки OneWayToSource не работают со свойствами зависимостей только для чтения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...