[문의]WPF Class 별로 바인딩 되었을 때 다른 View 시현

안녕하세요.

WPF에서 클래스 별로 다른 View를 보여주고 싶어서 문의드립니다.

클래스별로 갖고 있는 Property가 달라서 별도의 UserControl로 빼 놓았습니다.

이를 DataGrid에서 해당 아이템에 마우스를 올렸을 때 툴팁으로 각 해당하는 UserControl로 팝업 뷰를 만들어보려고 합니다.

즉, PersonClass Type의 데이터이면 UCPersonPropertyView(UserControl)로 툴팁해서 보여주고,
CarClass Type의 데이터이면 UCCarPropertyView로 툴팁을 보여줍니다.

사실 툴팁은 활용을 위한 예이고, 각 타입별로 어떻게 다르게 View에서 표현이 가능한지 보고 싶어서 문의드립니다.

DemoViewModel에서 DataGrid 시현되는 예제를 만들어 놨습니다.

확인해보시고, 가능한 방향이 있으면 안내 부탁드립니다.

감사합니다.

예제 파일 다운로드

3개의 좋아요

먼저 예제 파일을 살펴보지 않는 상태에서 답변을 드리는 점 이해 바랍니다.

ContentControlContentTemplateSelector 속성을 이용해 원하는 목적을 달성할 수 있을 것으로 보이는데요?

3개의 좋아요

@dimohy 님이 힌트를 주신대로 DataTemplateSelector를 쓰시면 될듯합니다.
GridDataTemplateSelector .cs 클래스 하나 만들었습니다.
바뀐 부분만 올려드립니다.

namespace Wpf.ClassType.View.Test.UI
{
    public class GridDataTemplateSelector : DataTemplateSelector
    {
        public DataTemplate CarTemplate { get; set; }
        public DataTemplate PersonTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item is ItemViewModel itemViewModel)
            {
                if (itemViewModel.Item is CarClass)
                {
                    return CarTemplate;
                }
                else if (itemViewModel.Item is PersonClass)
                {
                    return PersonTemplate;
                }
            }

            return null;
        }
    }
}

DataView.xaml

<UserControl x:Class="Wpf.ClassType.View.Test.UI.Views.DemoView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Wpf.ClassType.View.Test.UI.Views"
			 xmlns:ctrl="clr-namespace:Wpf.ClassType.View.Test.UI.Views.Controls" 
             xmlns:local1="clr-namespace:Wpf.ClassType.View.Test.UI"
             Background="SlateBlue"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <DataTemplate x:Key="CarTemplate">
            <Grid>
                <TextBlock Text="{Binding Item.Id}">
                    <TextBlock.Style>
                        <Style TargetType="TextBlock" >
                            <Setter Property="FontWeight" Value="Bold"/>
                        </Style>
                    </TextBlock.Style>
                    <TextBlock.ToolTip>
                        <StackPanel Orientation="Vertical">
                            <TextBlock Text="{Binding Item.CarName}"/>
                            <TextBlock Text="{Binding Item.Engine}"/>
                            <TextBlock Text="{Binding Item.Brand}"/>
                            <TextBlock Text="{Binding Item.CarType}"/>
                        </StackPanel>
                    </TextBlock.ToolTip>
                </TextBlock>
            </Grid>
        </DataTemplate>

        <DataTemplate x:Key="PersonTemplate">
            <Grid>
                <TextBlock Text="{Binding Item.Id}">
                    <TextBlock.Style>
                        <Style TargetType="TextBlock" >
                            <Setter Property="FontWeight" Value="Bold"/>
                        </Style>
                    </TextBlock.Style>
                    <TextBlock.ToolTip>
                        <StackPanel Orientation="Vertical">
                            <TextBlock Text="{Binding Item.PersonName}"/>
                            <TextBlock Text="{Binding Item.Age}"/>
                            <TextBlock Text="{Binding Item.Gender}"/>
                        </StackPanel>
                    </TextBlock.ToolTip>
                </TextBlock>
            </Grid>
        </DataTemplate>

        <local1:GridDataTemplateSelector x:Key="GridDataTemplateSelector"
                                         CarTemplate="{StaticResource CarTemplate}"
                                         PersonTemplate="{StaticResource PersonTemplate}"/>
    </UserControl.Resources>
    
    <Grid>
		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="10"/>
			<ColumnDefinition Width="*"/>
			<ColumnDefinition Width="10"/>
		</Grid.ColumnDefinitions>
		<Grid.RowDefinitions>
			<RowDefinition Height="20"/>
			<RowDefinition Height="*"/>
			<RowDefinition Height="20"/>
		</Grid.RowDefinitions>

		<DataGrid 
			Grid.Row="1"
			Grid.Column="1"
			CanUserAddRows="False"
			AutoGenerateColumns="False"
            IsSynchronizedWithCurrentItem="True"
            ItemsSource="{Binding Items}">
			<DataGrid.Columns>
				<DataGridTextColumn Header="Id"
									Binding="{Binding Path=Id}"/>
                <DataGridTemplateColumn Header="Item"
                                        CellTemplateSelector="{StaticResource GridDataTemplateSelector}"/>
            </DataGrid.Columns>
		</DataGrid>
	</Grid>
</UserControl>

1
2

4개의 좋아요

@WPF 세심하신 예제 소스코드에 감탄하고 갑니다. :smile:

image

지금 구현해주신 부분에서 정말 간단하게 추가해 본다면 요렇게 해볼 수 도 있겠습니다.



1. ContentContent 안에 PropertyView 바인딩

<TextBlock.ToolTip>
	<Grid>
		<!-- 어떻게 설정해야 Tooltip에서 클래스 타입별 UserControl을 설정해서
		팝업을 할 수 있을까?-->
        <ContentControl Content="{Binding Item.PropertyView}"/>
    </Grid>
</TextBlock.ToolTip>

2. BaseClass.cs에 PropertyView 속성 추가

public UserControl PropertyView { get; protected set; }

3. 각각의 PropertyView 유저컨트롤 인스턴스 생성 및 데이터 생성자에 할당

protected override Task OnActivateAsync(CancellationToken cancellationToken)
{
    // PropertyView 생성
    UCCarPropertyView carPropertyView = new UCCarPropertyView();
    UCPersonPropertyView personPropertyView = new UCPersonPropertyView();

    Items = new ObservableCollection<ItemViewModel>();
    // 객체마다 각각 생성자에 보내주기~ 
    Items.Add(new ItemViewModel(1, new CarClass(11, "소나타", 4, "현대", "승용차", carPropertyView)));
    Items.Add(new ItemViewModel(2, new CarClass(12, "싼타페", 4, "현대", "SUV", carPropertyView)));
    Items.Add(new ItemViewModel(3, new CarClass(13, "쏘렌토", 4, "현대", "SUV", carPropertyView)));
    Items.Add(new ItemViewModel(4, new CarClass(14, "GV80", 6, "현대", "SUV", carPropertyView)));
    Items.Add(new ItemViewModel(5, new PersonClass(16, "홍길동", 20, "남성", personPropertyView)));
    Items.Add(new ItemViewModel(6, new PersonClass(17, "홍길순", 25, "여성", personPropertyView)));
    Items.Add(new ItemViewModel(7, new PersonClass(18, "고길동", 30, "남성", personPropertyView)));
    Items.Add(new ItemViewModel(8, new PersonClass(19, "고길순", 28, "여성", personPropertyView)));

    return base.OnActivateAsync(cancellationToken);
}

각 모델 생성자에서도 PropertyView에 할당하기

public CarClass(int id, string name, int engine, string brand, string carType, UserControl propertyView)
    : base(id)
{
    CarName = name;
    Engine = engine;
    Brand = brand;
    CarType = carType;

    // 여기 또는 base 에서 할당
    // PersonClass에서도 동일하게~
    PropertyView = propertyView;
}

결과

타입 A 프로퍼티 창

image

타입 B 프로퍼티 창

image

4개의 좋아요

감사합니다. 외부에 있다보니 이제 확인했네요.
잘 참조하겠습니다.

1개의 좋아요

감사합니다!!
자세한 설명감사합니다.

1개의 좋아요

좋은 조언 감사합니다!

1개의 좋아요

감사합니다 해결책으로 너무 훌륭합니다!

1개의 좋아요