[WPF] ResourceDictionary에서 Command 호출하기

탭 안에 있는 버튼을 스타일로 가져와서 뷰모델에 있는 함수를 호출하려고 합니다.

<Grid>
    <TabControl>
        <TabItem Style="{StaticResource CustomTabItem}"/>
    </TabControl>
</Grid>

MainWindow.xaml에서 CustomTabItem이라는 style을 가져오려고 합니다.

App.xaml

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/themes/custombutton.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

App.xaml에서 호출할 수 있도록 리소스사전을 가져왔고요.

themes/custombutton.xaml

<Style x:Key="CustomTabItem" TargetType="{x:Type TabItem}">
    <Setter Property="Header" Value="ResourceDictionary"/>
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <Button x:Name="gdgd" 
                        Content="ResourceDictionary Button" 
                        Command="{Binding AClickCommand}"/>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

리소스사전에 위와 같이 정의를 해줬습니다.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainWindowViewModel();
    }
}
public class MainWindowViewModel
{
    private ICommand _AClickCommand;
    public ICommand AClickCommand
    {
        get
        {
            if (_AClickCommand == null) _AClickCommand = 
               new RelayCommand(OnAClick);

            return _AClickCommand;
        }
    }
    private void OnAClick()
    {
        System.Diagnostics.Trace.WriteLine("Resource Click");
    }
}

다음으로, MainWindow.xaml.cs의 생성자에서 뷰모델과 연결을 하고, 커맨드 객체를 연결해줬는데, 동작을 하지 않습니다.

라이브 시각적 트리를 찍어보면, tabitem의 Datacontext와 매핑이 되는데, 동작이 왜 안되는 지 궁금합니다.

1 Like
<TabItem Style="{StaticResource CustomTabItem}"/>`

<TabItem Content="{Binding}" Style="{StaticResource CustomTabItem}" />

로 변경해보세요.

3 Likes

image

참고로 라이브 시각적 트리에서 오른쪽 빨간색 상단 아이콘을 통해 전체 시각적 트리를 확인할 수 있습니다.

TabItem의 ContentTemplate는 중앙 빨간색 ContentPresenter에 의해 표현되는데 이때 DataContext가 Context로 전달되어야지만 올바르게 바인딩이 되어서 그렇습니다.

2 Likes

귀한 시간 내 주셔서 답변해주신 점 정말 감사드립니다.

Content="{Binding}"

이렇게 하면, '가장 가까운 상위에 있는 DataContext를 ContentPresenter와 연결되서 바인딩이 올바르게 이루어진다’라고 이해를 했는데, 맞을까요?

1 Like

네 맞습니다. 위의 시각적 트리를 보여드린 이유는 내부적으로 TabItem의 Content를 표현하기 위해 PART_...라는 ContentPresenter를 사용하는데 여기에 DataContext가 전달되었을 때 ContentTemplate으로 전달된 요소에 전달되지 않기 때문입니다. ContentPresenter는 Content 및 ContentTemplate가 쌍이 되어서 Content 내용이 Binding 대상이 되어서 그렇습니다.

2 Likes