Подтвердить что ты не робот

WPF привязка к родительскому DataContext

У нас есть приложение WPF со стандартным шаблоном MVVM, использующее Cinch (и, следовательно, MefedMVVM) для разрешения View → ViewModel. Это хорошо работает, и я могу привязать соответствующие элементы управления к свойствам в ViewModel.

В рамках конкретного представления у нас есть Infragistics XamGrid. Эта сетка привязана к ObservableCollection на ViewModel и отображает соответствующие строки. Тем не менее, у меня тогда есть конкретный столбец в этой сетке, который я пытаюсь связать текстовое значение TextBox с свойством в родительском DataContext, а не с ObservableCollection. Эта привязка не работает.

Мы рассмотрели несколько вариантов, включая:

  • Использование AncestorType для отслеживания дерева и привязки к DataContext родительского UserControl так (из отличный ответ на этот вопрос, а также этот...

    {Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
    
  • Указание ElementName и попытка напрямую настроить элемент управления верхнего уровня. смотрите здесь, если вы хотите прочитать об использовании ElementName.

  • Использование прокси-сервера FrameorkElement, определенного в ресурсах для UserControl, чтобы попробовать и "передать" контекст по мере необходимости. Мы определяем элемент, как показано ниже, затем ссылаемся как статический ресурс...

    <FrameworkElement x:Key="ProxyContext" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource Self}}"></FrameworkElement>
    

В этом случае привязка находит FrameworkElement, но не может получить доступ к чему-либо за пределами этого (при указании пути).

Просматривая, выглядит вполне вероятно, что это вызвано столбцами построения инфраструктуры Infragistics XamGrid вне дерева. Однако, даже если это так, по крайней мере должны быть варианты 2 или 3.

Наши последние мысли состоят в том, что это связано с привязкой V-VM, но даже с использованием Snoop нам еще предстоит найти то, что является точной проблемой. Я никоим образом не специалист с привязкой WPF, поэтому любые указатели будут оценены.

EDIT: Я нашел несколько примеров шаблонов из Infragistics здесь, которые я попробую.

EDIT 2: Как указано в @Dtex, шаблоны - это путь. Вот соответствующий фрагмент для использования с XamGrid:

<ig:GroupColumn Key="CurrentDate">
                <ig:GroupColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=DataContext.CurrentDateTest, RelativeSource={RelativeSource AncestorType=UserControl}}" />
                    </DataTemplate>
                </ig:GroupColumn.HeaderTemplate>
                <ig:GroupColumn.Columns>

Я оставил XML открытым... вы просто добавляли нужные столбцы, а затем закрывали соответствующие теги.

4b9b3361

Ответ 1

Я не знаю о XamGrid, но это то, что я сделаю со стандартным wpf DataGrid:

<DataGrid>
    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding DataContext.MyProperty, RelativeSource={RelativeSource AncestorType=MyUserControl}}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding DataContext.MyProperty, RelativeSource={RelativeSource AncestorType=MyUserControl}}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

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

Ответ 2

Из-за таких вещей, как общее правило, я стараюсь избегать как можно большего количества "хитрости" XAML и держать XAML как можно глубже и проще, а остальное - в ViewModel (или вложенных свойствах или IValueConverters и т.д., Если это действительно необходимо).

Если возможно, я бы предоставил ViewModel текущего DataContext ссылку (то есть свойство) на соответствующий родительский ViewModel

public class ThisViewModel : ViewModelBase
{
    TypeOfAncestorViewModel Parent { get; set; }
}

и напрямую связываться с ним.

<TextBox Text="{Binding Parent}" />