Доступ к родительскому DataContext из DataTemplate

У меня есть ListBox , который привязывается к дочерней коллекции в ViewModel. Элементы списка оформлены в виде таблицы данных, основанной на свойстве родительской ViewModel:

<Style x:Key="curveSpeedNonConstantParameterCell">
   <Style.Triggers>
      <DataTrigger Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified, 
          ElementName=someParentElementWithReferenceToRootDataContext}" 
          Value="True">
          <Setter Property="Control.Visibility" Value="Hidden"></Setter>
      </DataTrigger>
   </Style.Triggers>
</Style>

Я получаю следующую ошибку вывода:

System.Windows.Data Error: 39 : BindingExpression path error: 
 'CurveSpeedMustBeSpecified' property not found on 
   'object' ''BindingListCollectionView' (HashCode=20467555)'. 
 BindingExpression:Path=DataContext.CurveSpeedMustBeSpecified; 
 DataItem='Grid' (Name='nonConstantCurveParametersGrid');
 target element is 'TextBox' (Name=''); 
 target property is 'NoTarget' (type 'Object')

Поэтому, если я изменю выражение привязки на "Path = DataContext.CurrentItem.CurveSpeedMustBeSpecified « это работает, но только до тех пор, пока текст данных родительского пользовательского элемента управления является BindingListCollectionView . Это недопустимо, поскольку остальная часть пользовательского элемента управления автоматически связывается со свойствами CurrentItem в BindingList .

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

101
задан akjoshi 30 August 2012 в 14:43
поделиться

2 ответа

У меня возникли проблемы с относительным источником в Silverlight. После поиска и чтения я не нашел подходящего решения без использования дополнительной библиотеки привязки. Но вот другой подход для получения доступа к родительскому DataContext путем прямой ссылки на элемент, контекст данных которого вам известен. Он использует Binding ElementName и работает достаточно хорошо, если вы уважаете свое собственное именование и не имеете интенсивного повторного использования шаблонов / стилей в компонентах:

<ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Button Content={Binding MyLevel2Property}
              Command={Binding ElementName=level1Lister,
                       Path=DataContext.MyLevel1Command}
              CommandParameter={Binding MyLevel2Property}>
      </Button>
    <DataTemplate>
  <ItemsControl.ItemTemplate>
</ItemsControl>

Это также работает, если вы поместите кнопку в Стиль / Шаблон :

<Border.Resources>
  <Style x:Key="buttonStyle" TargetType="Button">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">
          <Button Command={Binding ElementName=level1Lister,
                                   Path=DataContext.MyLevel1Command}
                  CommandParameter={Binding MyLevel2Property}>
               <ContentPresenter/>
          </Button>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</Border.Resources>

<ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Button Content="{Binding MyLevel2Property}" 
              Style="{StaticResource buttonStyle}"/>
    <DataTemplate>
  <ItemsControl.ItemTemplate>
</ItemsControl>

Сначала я подумал, что x: Имена родительских элементов не являются доступный из шаблонного элемента, но, поскольку я не нашел лучшего решения, я просто попробовал, и он отлично работает.

149
ответ дан 24 November 2019 в 04:38
поделиться

Вы можете использовать RelativeSource , чтобы найти родительский элемент, например:

Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified, 
RelativeSource={RelativeSource AncestorType={x:Type local:YourParentElementType}}}"

См. этот вопрос SO для получения дополнительных сведений о RelativeSource .

43
ответ дан 24 November 2019 в 04:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: