121

ListBoxViewModelの子コレクションにバインドするがあります。リストボックスアイテムは、親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"と機能しますが、親ユーザーコントロールのデータコンテキストが。である場合に限りますBindingListCollectionViewCurrentItem残りのユーザーコントロールはBindingList自動的にのプロパティにバインドされるため、これは受け入れられません。

親データコンテキストがコレクションビューまたは単一のアイテムであるかどうかに関係なく機能するように、スタイル内でバインディング式を指定するにはどうすればよいですか?

4

6 に答える 6

169

Silverlightの相対ソースに問題がありました。検索して読んだ後、追加のバインディングライブラリを使用しないと適切な解決策が見つかりませんでした。ただし、データコンテキストを知っている要素を直接参照することにより、親DataContextにアクセスするための別のアプローチがあります。独自の命名を尊重し、コンポーネント間で/をBinding ElementName頻繁に再利用しない限り、これは非常にうまく機能します。templatesstyles

<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>

Styleこれは、ボタンを/に入れた場合にも機能しますTemplate

<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:Names、テンプレート化されたアイテム内から親要素のにアクセスできないと思いましたが、より良い解決策が見つからなかったので、試してみましたが、問題なく動作します。

于 2010-08-23T12:55:32.690 に答える
53

RelativeSource次のように、親要素を見つけるために使用できます-

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

の詳細については、この SO の質問を参照してくださいRelativeSource

于 2010-08-04T12:27:25.173 に答える
18

私はWPFで似たようなことをする方法を探していましたが、この解決策を得ました:

<ItemsControl ItemsSource="{Binding MyItems,Mode=OneWay}">
<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel Orientation="Vertical" />
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <RadioButton 
            Content="{Binding}" 
            Command="{Binding Path=DataContext.CustomCommand, 
                        RelativeSource={RelativeSource Mode=FindAncestor,      
                        AncestorType={x:Type ItemsControl}} }"
            CommandParameter="{Binding}" />
    </DataTemplate>
</ItemsControl.ItemTemplate>

これが他の誰かに役立つことを願っています。ItemsControls に自動的に設定されるデータ コンテキストがあり、このデータ コンテキストにMyItemsは、コレクションである 2 つのプロパティと、1 つのコマンド 'CustomCommand' があります。ItemTemplateは を使用しているためDataTemplateDataContext上位レベルの には直接アクセスできません。次に、親の DC を取得するための回避策は、相対パスを使用してItemsControlタイプ別にフィルター処理することです。

于 2011-06-03T00:54:41.683 に答える