내용 보기

작성자

관리자 (IP : 172.17.0.1)

날짜

2020-07-10 02:31

제목

[WPF] HierarchicalDataTemplate 안에서 Command 바인딩 처리하기


WPF 기본 컨트롤의 TreeView 컨트롤을 사용하면서 커스텀 하게 TreeNode를 표시해야 할 경우
HierarchicalDataTemplate을 사용하여 구현 할 수 있다.
이 경우 HierarchicalDataTemplate안에서 ContextMenu나 Button컨트롤 등에 Command 바인딩 처리를 해야 할 경우 일반적으로 사용하는 바인딩 처리를 하는 경우 HierarchicalDataTemplate에 ItemsSource를 사용하거나
TreeView 컨트롤에 ItemsSource를 사용한다면 Command 처리를 하는 컨트롤 대상의 부모 ItemsSource를 따르게 되므로 정상적으로 바인딩 처리가 되지 않는다.
이럴 경우 다음과 같은 방법으로 해결 할 수 있다.

방법1 부모 컨트롤의 Tag속성 이용

HierarchicalDataTemplate안에 ContextMenu를 사용 할 경우 방법2를 이용했을 경우 제대로 되지 않아 아래 방법 처럼 부모 컨트롤의 Tag속성을 이용하였다.

<TreeView x:Name="xPolicyTemplateTreeView" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding PolicyTemplateTree}">
                            <TreeView.ItemContainerStyle>
                                <Style TargetType="TreeViewItem">
                                    <Setter Property="IsExpanded" Value="True" />
                                </Style>
                            </TreeView.ItemContainerStyle>
                            <TreeView.ItemTemplate>
                                <!--Root Note (Dummy Root)-->
                                <HierarchicalDataTemplate DataType="{x:Type CDTTemplateMgr:PolicyTemplateNode}" ItemsSource="{Binding ChildNodes, UpdateSourceTrigger=PropertyChanged}">
                                    <Grid Tag="{Binding DataContext, ElementName=xMainGrid}">
                                        <StackPanel Orientation="Horizontal">
                                            <TextBlock Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="10, 0, 10, 0" />
                                        </StackPanel>
                                        <Grid.ContextMenu>
                                            <ContextMenu>
                                                <MenuItem Header="템플릿 신규 생성" Command="{Binding PlacementTarget.Tag.CreateTempleate, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
                                                <MenuItem Header="템플릿 복사 후 생성" Command="{Binding ElementName=xMainGrid, Path=CreateCopyTempleate}" CommandParameter="{Binding ElementName=xPolicyTemplateTreeView, Path=SelectedItem}"/>
                                                <Separator />
                                                <MenuItem Header="템플릿 수정" Command="{Binding ElementName=xMainGrid, Path=ModifyTempleate}" CommandParameter="{Binding ElementName=xPolicyTemplateTreeView, Path=SelectedItem}"/>
                                                <MenuItem Header="템플릿 삭제" Command="{Binding ElementName=xMainGrid, Path=DeleteTempleate}" CommandParameter="{Binding ElementName=xPolicyTemplateTreeView, Path=SelectedItem}"/>
                                            </ContextMenu>
                                        </Grid.ContextMenu>
                                    </Grid>
 
                                    <!--2 Depth Note-->
                                    <HierarchicalDataTemplate.ItemTemplate>
.
.
생략..
.
.
cs

방법2 RelativeSource의 AncestorLevel=2 이용

<TreeView ItemsSource="{Binding Items}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding SubItems}">                
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <Button Command="??CmdOnDtaCntxtOfHierDtaTmplt" 
                            CommandParameter="{Binding}" />                                 
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>
cs

위 상황일 때

<Button Command="{Binding DataContext.Command, 
        RelativeSource={RelativeSource AncestorLevel=2, AncestorType=TreeViewItem}}"
        CommandParameter="{Binding}" />
cs


출처1

출처2