programing

DataTemplate에서 상위 DataContext에 액세스합니다.

easyjava 2023. 4. 19. 23:34
반응형

DataTemplate에서 상위 DataContext에 액세스합니다.

는 나나 a a a가 있다ListBoxView Model view view view 。"View Model" "Data Template" "Data Template" "View Model" "Data Template" "Data Template" "Data Template" "View Model" "Data Template" "Data Template" "View Model"

<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"가 DataContext일 에만 동작합니다.BindingListCollectionView 부분은 '사용할 수 없다' 되지 않습니다CurrentItem BindingList자동으로.

상위 데이터 컨텍스트가 컬렉션 뷰인지 단일 항목인지에 관계없이 작동하도록 스타일 내에서 바인딩 식을 지정하려면 어떻게 해야 합니까?

Silverlight의 관련 정보원과 문제가 있었습니다.검색 후 읽어본 결과 추가 바인딩 라이브러리를 사용하지 않고는 적절한 솔루션을 찾을 수 없었습니다.그러나 데이터 컨텍스트를 알고 있는 요소를 직접 참조하여 상위 DataContext에 액세스할있는다른 방법이 있습니다.사용하다Binding ElementName 하지 가 있습니다.templates/styles다음 중 하나:

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

에 나는 음음 at at at at at at at라고 했다.x:Names템플릿화된 아이템 내에서는 부모 요소에 접근할 수 없지만, 더 나은 솔루션을 찾을 수 없었기 때문에 시도해보니 정상적으로 작동합니다.

하시면 됩니다.RelativeSource원소를 수 .

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

자세한 내용은 이 SO 질문을 참조하십시오.RelativeSource.

상대 소스 vs.요소명

이 두 가지 접근방식은 동일한 결과를 얻을 수 있습니다.

상대 소스

Binding="{Binding Path=DataContext.MyBindingProperty, 
          RelativeSource={RelativeSource AncestorType={x:Type Window}}}"

에서 Window 예에서는하여 Visual Tree 유형(Visual Tree)의 Window에 수 .DataContextPath=DataContext....이 방법의 장점은 이름에 얽매일 필요가 없고 역동적이라는 것입니다만, 시각 트리를 변경하면 이 메서드에 영향을 미쳐 망가질 수 있습니다.

요소명

Binding="{Binding Path=DataContext.MyBindingProperty, ElementName=MyMainWindow}

스태틱을 합니다.Name.물론 이 방법을 어기지 않으려면 명명 규칙을 지켜야 합니다., 한 것은 '만들다'를만 하면 .필요한 것은, 다음의 항목을 지정하기만 하면 됩니다.Name="..."를 선택합니다.

3가지 타입( 「 」, 「3」) 입니다.RelativeSource, Source, ElementName할 수 , 기사에 , 하는 것이 도 같은 기능을 할 수 있습니다만, 다음의 MSDN 기사에 의하면, 각각 독자적인 분야에서 사용하는 것이 좋습니다.

방법: 바인딩 소스 지정

페이지 하단의 표에서 각 설명에 대한 간단한 설명과 더 자세한 링크에 대한 링크를 찾습니다.

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-이것은 컬렉션입니다.커스텀 커맨드'를 선택합니다.그유 the the because because 。ItemTemplate요.DataTemplate , . . . . . . . .DataContext직접 접속할 수 없습니다.하여 DC로 .ItemsControldiscloss.discloss.

문제는 DataTemplate가 적용된 요소의 일부가 아니라는 것입니다.

즉, 템플릿에 바인드하면 컨텍스트가 없는 무언가에 바인드됩니다.

단, 템플릿 내에 요소를 넣으면 해당 요소가 부모에 적용되면 컨텍스트가 취득되고 바인딩이 기능합니다.

그래서 이건 안 돼

<DataTemplate >
    <DataTemplate.Resources>
        <CollectionViewSource x:Key="projects" Source="{Binding Projects}" >

하지만 이것은 완벽하게 작동한다.

<DataTemplate >
    <GroupBox Header="Projects">
        <GroupBox.Resources>
            <CollectionViewSource x:Key="projects" Source="{Binding Projects}" >

왜냐하면 데이터 템플릿이 적용된 후 그룹 박스는 부모에 배치되어 컨텍스트에 액세스할 수 있기 때문입니다.

따라서 템플릿에서 스타일을 제거하고 템플릿의 요소로 이동하기만 하면 됩니다.

항목 컨트롤의 컨텍스트는 ComboBox용 ComboBoxItem 컨트롤이 아닌 항목이며, 이 경우 대신 ItemContainerStyle 컨트롤을 사용해야 합니다.

이렇게 '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아이다'를해서 풀 수 있어요.ElementName=SomethingJuve ★★★★★★★★★★★★★★★★.

하지만!

(이런 종류의 바인딩을 사용하는) 자녀 요소가 부모 컨트롤에서 지정한 것과 동일한 요소 이름을 사용하는 사용자 컨트롤인 경우 바인딩이 잘못된 개체로 이동합니다!!

이 게시물이 해결책이 아닌 것은 알지만, 바인딩에서 ElementName을 사용하는 모든 사용자는 런타임 버그일 가능성이 있기 때문에 알아야 한다고 생각했습니다.

<UserControl x:Class="MyNiceControl"
             x:Name="TheSameName">
   the content ...
</UserControl>

<UserControl x:Class="AnotherUserControl">
        <ListView x:Name="TheSameName">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <MyNiceControl Width="{Binding DataContext.Width, ElementName=TheSameName}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
</UserControl>

, 하다, 하다, 하다, 하다를 도 할 수 있어요.., 의 악세스를 얻을 수 Source여기

필요에 따라서, 마침표(.) 패스를 사용하고, 현재의 송신원에 바인드 할 수 있습니다.예를 들어 Text="{Binding}"은 Text="{Binding Path="와 동일합니다.}".

것을 .DataContext에 inside inside inside Tag부모에게 양해를 구한다. DataContext

ResourceDictionary.xaml:

<Style x:Key="SomeControl" TargetType="ItemsControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Grid Tag="{Binding .}">
                        <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=Tag.DataContext.SomeName}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Main Window.xaml:

<ItemsControl Style="{StaticResource SomeControl}"/>

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
   public MainWindow()
   {
      //...
      SomeName = "Your value";
   } 
   public string SomeName { get; set; }
}

언급URL : https://stackoverflow.com/questions/3404707/access-parent-datacontext-from-datatemplate

반응형