«System.Windows.Data.MultiBinding» не является допустимым значением для свойства «Текст».

Я пытаюсь написать собственный MarkupExtension, который позволяет мне использовать мои собственные механизмы для определения привязки, однако, когда я пытаюсь вернуть MultiBinding из моего MarkupExtension, я получаю указанное выше исключение.

У меня есть:

<TextBlock Text="{my:CustomMarkup ...}" />

CustomMarkup возвращает MultiBinding, но, видимо, Text не нравится, когда его устанавливают в MultiBinding. Почему это работает, когда я говорю:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding ... />
    </TextBlock.Text>
</TextBlock>

Но это не работает так, как я это делаю?


person devios1    schedule 15.06.2010    source источник


Ответы (2)


Не возвращайте сам MultiBinding. Вместо этого верните результат MultiBinding.ProvideValue.

Кстати, что именно вы делаете в своем расширении разметки? Возможно, вы могли бы просто наследовать от MultiBinding, если вам не нужно переопределять ProvideValue (который запечатан). Вы можете добиться практически всего, просто установив соответствующие Converter и другие свойства.

person Thomas Levesque    schedule 15.06.2010
comment
Как раз то, что я собирался написать, но вы меня опередили. - person Ray Burns; 16.06.2010
comment
Интересно. Мое пользовательское расширение, по сути, дает мне возможность определять привязки как результаты метода в моем программном коде и получать зависимости для привязки из пользовательских атрибутов, которые я прикрепляю к методу. Это довольно круто, если я сам так не говорю. :) Думаю опубликовать, если получится. - person devios1; 16.06.2010

Провел некоторое расследование, и оказалось, что я должен фактически установить привязку в методе MarkupExtension ProvideValue, а затем вернуть текущее значение привязки. Немного нелогично, но пока, похоже, работает!

Вот примерно что у меня получилось:

public override object ProvideValue( IServiceProvider serviceProvider ) {
    IProvideValueTarget valueProvider = (IProvideValueTarget)serviceProvider.GetService( typeof( IProvideValueTarget ) );
    // only need to do this if they're needed in your logic:
    object @target = valueProvider.TargetObject;
    object @property = valueProvider.TargetProperty;

    MultiBinding result = new MultiBinding();

    // set up binding as per custom logic...

    return result.ProvideValue( serviceProvider );
}

Добавьте немного логики, слегка припудрите обработку ошибок и подавайте.

Обновление: оказалось, что MultiBinding.ProvideValue() подключает саму привязку на основе информации о цели и свойствах в serviceProvider. Это намного чище.

person devios1    schedule 15.06.2010
comment
Я думаю, что MultiBinding.ProvideValue уже выполняет BindingOperations.SetBinding... так что вы делаете это дважды - person Thomas Levesque; 16.06.2010
comment
P.S. Я просто использую символы '@', чтобы переменные выглядели по-особенному... не служит никакой функциональной цели. - person devios1; 16.06.2010
comment
Подождите, как это могло быть? Он не знает, что такое привязка, пока я ее не установил. - person devios1; 16.06.2010
comment
О, я вижу, он получает их от serviceProvider... интересно. - person devios1; 16.06.2010
comment
Вы делаете слишком много. Чтобы получить набор привязок, вам нужно только вернуть BindingExpressionBase (НЕ BindingBase) из вашего ProvideValue. - person Ray Burns; 16.06.2010
comment
Ты прав, это работает, круто. По крайней мере, это немного чище. Я обновлю ответ. - person devios1; 16.06.2010