Binding в WPF (продолжение)
От: Fortnum  
Дата: 29.10.10 22:21
Оценка:
Разбирался с Coercion в биндинге WPF, и наткнулся на старую тему
Автор:
Дата: 21.07.09
. Попытался разобраться и ответить на вопрос "баг или фича?" Оказывается, фича, обеспечивающая отсутствие зацикливаний при смене значений зависимых свойств (dependency properties).

Да вот, собственно, я даже нарисовал (см. ниже). Еще подумал, что было бы, если бы CLR-property у ТС той темы получал бы уже Coerced Value. Был бы "плохой дизайн" Тоже его нарисовал. Т.е. устойчивость биндинга обеспечивается тем, что у любого DependecnyProperty может быть только один источник. А т.к. этот источник может быть другим DependencyProperty со своим CoerceValueCallback'ом, то возникает проблема зацикливания биндинга. Вот и объяснение.

Прикрепил еще проектик по теме. Только я убрал DataContext'ный объект с CLR-property — ни при чем он здесь Заменил TextBox'ами. В общем, в проекте этот эффект сразу виден, кому надо скачает и посмотрит, здесь код приводить не буду.

Вот картинка:

Re: Binding в WPF (продолжение)
От: Fortnum  
Дата: 29.10.10 22:57
Оценка:
А в доказательство того, что Window.TextBox2 может влиять на то, что будет записано в Window.TextBox1, несмотря на то, что Window.TextBox1 привязан к UserControl.Value как к источнику, вот еще более интересный проект со строками. Надо вбить что-нибудь в UserControl.TextBox2, нажать Tab, чтобы сместился фокус, и увидеть, что в Window.TextBox2 будет то, что вы набрали + 2 звездочки, а во всех остальных TextBox'ах + 3 звездочки, хотя в UserControl.Value_Coerce_Shared стоит + "*".

Секрет в том, что Window.TextBox2 является MyTextBox'ом, который я унаследовал от стандартного TextBox'а и сделал ему OverrideMetadata, где добавляю 2 звездочки. В итоге, в UserControl.TextBox2 после смены фокуса возвращается то, что вы набрали + 1 + 2 = +3 звездочки!

Вот определение MyTextBox:
public class MyTextBox : TextBox
{
    public MyTextBox()
    {
        TextProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata("This is MyTextBox's default value",
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
            Text_Changed_Shared, Text_Coerce_Shared));
    }

    static void Text_Changed_Shared(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    }

    static object Text_Coerce_Shared(DependencyObject d, object baseValue)
    {
        return (string)baseValue + "**";
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.