Привязка данных вне визуального дерева. Соединение контекста данных

Я пытаюсь привязать динамическое поведение к визуальному элементу вне логических и визуальных деревьев WPF.

Моя проблема заключается в том, что цвет графика RadChart задается в (квази-путь): RadChart.SeriesMapping.LineSeriesDefinition.Appearance.Stroke

Первоначально я хотел связать это со свойством текстового данных диаграммы в XAML. Наивно, я просто написал обычный {Binding PlotBrush}

Компилятор возвратил ошибку "Не удается найти управляющий FrameWorkelement". После прочтения, я считаю, что это означает, что разрешение текстового контекста иерархии не сработало. Поскольку его предки (говоря на XAML) имеют другие типы, отличные от FrameWorkElement и другие отношения, отличные от содержимого элемента управления содержимым. По крайней мере, это мое нынешнее понимание. Пожалуйста, поправьте меня.

Итак, я нашел "Мост DataContext" http://www.codeproject.com/KB/WPF/AttachingVirtualBranches.aspx

Проще говоря, это говорит о том, что вы связываете свойство datacontext элемента framework, которому во время выполнения присваивается текст datacontext (а не тот, который его наследует), с datacontext экземпляра FrameWorkElement в ресурсах. Затем тот же экземпляр объекта ресурса используется для привязки к свойству datacontext "ветви", которую вы хотите "присоединить" к динамике наследования DataContext. Но автору статьи была предоставлена ​​роскошь того, что он мог осуществить валидацию прав потребителей наблюдаемой собственности. SolidColorBrush запечатан, и я предполагаю, что было бы довольно сложно реализовать полную кисть, даже используя декоратор.

В моем случае это не помогает мне делать то, что я хочу, но я "так близко". Поэтому мне интересно, есть ли какой-нибудь аспект трюков XAML, который мог бы мне помочь.

<Window.Resources>
    <local:FrameWorkElement x:Key="DataContextBridge"/>
</Window.Resources>

Однако неясно, как я это использую. Нет объекта, чей текст данных должен быть установлен. AppearanceSettings не является FrameWorkElement.

<telerik:SeriesAppearanceSettings>
   <telerik:SeriesAppearanceSettings.Stroke>
       Ok, how do I use the fact that I can access the datacontext here?                                         
   </telerik:SeriesAppearanceSettings.Stroke>
</telerik:SeriesAppearanceSettings>

Итак, следующий шаг был более влажным, я мог каким-то образом получить объект кисти напрямую. Я экспериментировал с такими вещами, просто возился:

.cs:

public class ObservableBrush : FrameworkElement
{
    public Brush Brush
    {
        get { return (Brush) GetValue(BrushProperty); }
        set { SetValue(BrushProperty, value); }
    }

    public static readonly DependencyProperty BrushProperty =
        DependencyProperty.Register("Brush", typeof (Brush), typeof (ObservableBrush), new UIPropertyMetadata(new SolidColorBrush(Colors.Black)));
}

Вершина XAML:

<Window.Resources>
    <local:ObservableBrush x:Key="StrokeBrush"/>
</Window.Resources>

Встроенный XAML:

<telerik:SeriesAppearanceSettings.Stroke>
     <Binding Path="Brush">
     <Binding.Source>
          <Binding Source="{StaticResource ResourceKey=StrokeBrush}" Path="DataContext"/>
     </Binding.Source>                                            
     </Binding>                                     
</telerik:SeriesAppearanceSettings.Stroke>

"Связывание" не является элементом фреймворка, равно как и "Источник" не является свойством зависимости, поэтому среда выполнения, конечно, жалуется. Мне известно, что свойство Brush никогда не будет возвращать ничего, кроме значения по умолчанию, указанного при регистрации свойства зависимостей.

Я как бы иду на второй день прямо по этой проблеме. Я думаю, что мои следующие две попытки будут: * Сделать ObservableBrush реальной кистью. Затем установите его программно (эффективно используя вместо этого стандартную динамическую привязку ресурса). Мне это не нравится Я хотел сделать работу с данными. * Мост ЩЕТКА вместо DATACONTEXT.

XAML часть этого прекрасно работает:

<telerik:SeriesAppearanceSettings.Stroke>
     <Binding Source="{StaticResource ResourceKey=StrokeBrush}" Path="Brush"/>
</telerik:SeriesAppearanceSettings.Stroke>

Но опять же, как мне связать Brush со свойством DataContext? Есть ли какое-то переопределение, которое я могу использовать в ObservableBrush, чтобы Brush динамически следовал за тем, что в текстовом тексте?

Как насчет создания поддельного визуального элемента в дереве, а затем связать с ним ДВА привязки?

<!-- Within the visual tree scope -->
<SomeFrameWorkElementType>
     <SomeFrameWorkElemetType.SomeBrushProp>
         <Binding Source="{StaticResource ResourceKey=StrokeBrush}" Path="Brush" Mode="OneWayToSource"/>
         <Binding Stroke/>
     </SomeFrameWorkElemetType.SomeBrushProp>
<SomeFrameWorkElementType>

И это как-то "соединит" две привязки?

Или есть какой-то (не) официальный "класс помощника" для этого типа функциональности?

Или я лаю не на том дереве, и (намного) лучше решить эту проблему в коде через динамическое связывание ресурсов?

Любые мысли или замечания о том, как продолжить об этом? Кроме моего очевидного саморазрушения за то, что я настаивал на привязке данных, когда динамические ресурсы должны были решать это.

1 ответ

Решение

Вы нашли там хорошую статью Джоша Смита, но она немного устарела. Около года спустя тот же самый парень написал еще лучшую статью, в которой освещается практически тот же вопрос, но есть лучшие ответы: контекст искусственного наследования

Там он использует класс DataContextSpy и пока я не до конца понимаю, чего вы пытаетесь достичь, я постараюсь показать вам, как вы это используете:

<Grid><!-- this is some container where its DataContext has the PlotBrush Property-->
    <Grid.Resources>
        <spy:DataContextSpy x:Key="Spy"/>
    </Grid.Resources>
    <telerik:thisIsYourControl>
        <telerik:SeriesAppearanceSettings.Stroke>
             <Binding Source="{StaticResource Spy}" Path="DataContext.PlotBrush"/>
        </telerik:SeriesAppearanceSettings.Stroke>
    </telerik:thisIsYourControl>
<Grid>

Я надеюсь, что это помогает и работает для вас. Раньше я не использовал элементы управления telerik, поэтому не могу написать полный пример, но все же надеюсь, что это поможет.

Другие вопросы по тегам