Program Tip

XAML (.NET 4 Framework 이전)에서 제네릭 형식을 지정할 수 있습니까?

programtip 2020. 10. 27. 23:09
반응형

XAML (.NET 4 Framework 이전)에서 제네릭 형식을 지정할 수 있습니까?


XAML에서 특정 형식이 표시 될 때마다 템플릿이 사용되도록 DataTemplate을 선언 할 수 있습니다. 예를 들어이 DataTemplate은 TextBlock을 사용하여 고객의 이름을 표시합니다.

<DataTemplate DataType="{x:Type my:Customer}">
    <TextBlock Text="{Binding Name}" />
</DataTemplate>

IList <Customer>가 표시 될 때마다 사용할 DataTemplate을 정의 할 수 있는지 궁금합니다. 따라서 ContentControl의 Content가 ObservableCollection <Customer> 인 경우 해당 템플릿을 사용합니다.

{x : Type} 태그 확장을 사용하여 XAML에서 IList와 같은 제네릭 형식을 선언 할 수 있습니까?


상자에서 꺼내지 마십시오. 하지만 그렇게 한 진취적인 개발자가 있습니다.

예를 들어 Microsoft의 Mike Hillberg는 이 게시물 에서 이를 사용했습니다 . 물론 Google에는 다른 것이 있습니다.


XAML에서 직접적으로는 아니지만 DataTemplateSelector올바른 템플릿을 선택하기 위해 XAML에서를 참조 할 수 있습니다.

public class CustomerTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item,
                                                DependencyObject container)
    {
        DataTemplate template = null;
        if (item != null)
        {
            FrameworkElement element = container as FrameworkElement;
            if (element != null)
            {
                string templateName = item is ObservableCollection<MyCustomer> ?
                    "MyCustomerTemplate" : "YourCustomerTemplate";

                template = element.FindResource(templateName) as DataTemplate;
            } 
        }
        return template;
    }
}

public class MyCustomer
{
    public string CustomerName { get; set; }
}

public class YourCustomer
{
    public string CustomerName { get; set; }
}

리소스 사전 :

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    >
    <DataTemplate x:Key="MyCustomerTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="150"/>
            </Grid.RowDefinitions>
            <TextBlock Text="My Customer Template"/>
            <ListBox ItemsSource="{Binding}"
                     DisplayMemberPath="CustomerName"
                     Grid.Row="1"/>
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="YourCustomerTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="150"/>
            </Grid.RowDefinitions>
            <TextBlock Text="Your Customer Template"/>
            <ListBox ItemsSource="{Binding}"
                     DisplayMemberPath="CustomerName"
                     Grid.Row="1"/>
        </Grid>
    </DataTemplate>
</ResourceDictionary>

창 XAML :

<Window 
    x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" 
    Height="300" 
    Width="300"
    xmlns:local="clr-namespace:WpfApplication1"
    >
    <Grid>
        <Grid.Resources>
            <local:CustomerTemplateSelector x:Key="templateSelector"/>
        </Grid.Resources>
        <ContentControl 
            Content="{Binding}" 
            ContentTemplateSelector="{StaticResource templateSelector}" 
            />
    </Grid>
</Window>

뒤에있는 윈도우 코드 :

public partial class Window1
{
    public Window1()
    {
        InitializeComponent();
        ObservableCollection<MyCustomer> myCustomers
            = new ObservableCollection<MyCustomer>()
        {
            new MyCustomer(){CustomerName="Paul"},
            new MyCustomer(){CustomerName="John"},
            new MyCustomer(){CustomerName="Mary"}
        };

        ObservableCollection<YourCustomer> yourCustomers
            = new ObservableCollection<YourCustomer>()
        {
            new YourCustomer(){CustomerName="Peter"},
            new YourCustomer(){CustomerName="Chris"},
            new YourCustomer(){CustomerName="Jan"}
        };
        //DataContext = myCustomers;
        DataContext = yourCustomers;
    }
}

T를 지정하는 파생 클래스에서 제네릭 클래스를 래핑 할 수도 있습니다.

public class StringList : List<String>{}

XAML에서 StringList를 사용합니다.


aelij ( WPF Contrib 프로젝트 의 프로젝트 코디네이터 )에는 다른 방법 이 있습니다.

더 멋진 것은 (미래에 언젠가는 꺼지더라도) ... XAML 2009 (XAML 2006이 현재 버전 임)가이를 기본적으로 지원한다는 것입니다. 자세한 내용은이 PDC 2008 세션확인하십시오 .


.net 프레임 워크의 재전송 된 버전에서는이 작업을 수행 할 수 있습니다.

Check the Generics in XAML documentation. You'd need to use x:TypeArguments; there are some restrictions so read the documentaion first.

Also see the How to specify generic type argument in XAML question on Stackoverflow


Quite defeats the purpose of a generic, but you could define a class that derives from the generic like so, with the sole purpose of being able to use that type in XAML.

public class MyType : List<int> { }

And use it in xaml e.g. like

<DataTemplate DataType={x:Type myNamespace:MyType}>

참고URL : https://stackoverflow.com/questions/185349/can-i-specify-a-generic-type-in-xaml-pre-net-4-framework

반응형