在XAML中声明类型列表

4
我正在使用一个值转换器,它需要获取类型列表,这是转换器的属性。如果我使用双精度值列表,我可以使用以下语法(按预期工作):
public class MyConverter : IValueConverter
{
    public List<double> MyList { get; set; }

    // ...
}

XAML (可扩展应用程序标记语言)
<Converter:MyConverter x:Key="MyConverter">
    <Converter:MyConverter.MyList>
        <System.Double>1</System.Double>
        <System.Double>2</System.Double>
    </Converter:MyConverter.MyList>
</Converter:MyConverter>

但是如果我尝试使用这种方法来处理类型列表,就会抛出异常:
Object of type 'System.RuntimeType' cannot be converted to type 'System.Collections.Generic.List`1[System.Type]'

这是我的转换器及其使用:

代码

public class MyConverter : IValueConverter
{
    public List<Type> MyList { get; set; }

    // ...
}

XAML(可扩展应用程序标记语言)
<Converter:MyConverter x:Key="MyConverter">
    <Converter:MyConverter.MyList>
        <x:Type TypeName="MyType1" />
        <x:Type TypeName="MyType2" />
    </Converter:MyConverter.MyList>
</Converter:MyConverter>

我猜XAML语法是错误的,但我找不到正确的语法。

你们中有没有任何一个答案对你有用? - Artiom
@Artiom,你的回答非常有帮助,谢谢。不过在我决定什么是一个令人满意的答案之前,我想更深入地了解一下这个问题。 - MatthiasG
你尝试过给出的解决方案吗?我已经更新了我的解决方案,而colinsmith的解决方案似乎也有效。 - Artiom
2个回答

2
似乎是XAML设计师中的错误。下面给出的代码对我有用。我可以构建和运行应用程序。但在设计师中,R#会突出显示两行System:Type并崩溃,每行有以下两个错误:

错误1 Type'Type'不可用作对象元素,因为它不是公共的或未定义公共无参构造函数或类型转换器。
错误2 类型“Type”不支持直接内容。 所以当我之前尝试该解决方案时(在提供之前的解决方案之前),我以为我做错了什么。但编译器在构建时仍然没有给出任何错误。无论如何,这就是它的样子:

<Window.Resources>
    <local:Holder x:Key="one">
        <local:Holder.Types>
            <System:Type>System:Int32</System:Type>
            <System:Type>System:Double</System:Type>
        </local:Holder.Types>
    </local:Holder>
</Window.Resources>
<Grid >
    <ListBox DataContext="{StaticResource one}" ItemsSource="{Binding Path=Types, Converter={StaticResource one}}" />
</Grid>

就目前而言,区别在于声明方式。您需要使用System.Type而不是x:Type。

以下是示例代码:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;
using System.Linq;

namespace stackProjects
{
    public class Holder : IValueConverter
    {
        public List<Type> Types { get; set; }

        public Holder()
        {
            Types=new List<Type>();
        }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Types.Select(x => x.Name).ToList();
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

正如我所说,这是因为Type类是抽象的。希望这可以帮到你。

谢谢你的回答。虽然我不想放弃泛型,但我暂时会停止使用它们。我只是想知道为什么在使用双精度值列表时,泛型没有问题。 - MatthiasG

1

好的,下面的示例已经编译并运行了...我看到转换器被调用,并且列表被填充了2个类型对象。可能有更好的方法来完成它。


这是我使用的完整代码:

namespace WpfApplication4
{
    public class MyConverter : IValueConverter
    {
        public IList<Type> MyList { get; set; }

        public MyConverter()
        {
            MyList = new List<Type>();
        }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class MyType
    {
        public string Name { get; set; }

        public MyType()
        {

        }
    }
}

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication4"
        xmlns:runtime="clr-namespace:System.Runtime.InteropServices;assembly=mscorlib"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <sys:String x:Key="testdata">TestData</sys:String>
        <x:Array x:Key="listoftypes" Type="{x:Type sys:Type}">
            <x:Type Type="local:MyType"/>
            <x:Type Type="local:MyType"/>
        </x:Array>
        <local:MyConverter x:Key="myconv" MyList="{StaticResource listoftypes}"/>
    </Window.Resources>
    <Grid>
        <TextBlock Text="{Binding Source={StaticResource testdata}, Converter={StaticResource myconv}}"/> 
    </Grid>
</Window>

1
也许我应该澄清一下问题。双重列表转换器正在工作,并且只是想展示它如何正确工作。它只是不能处理类型列表。 - MatthiasG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接