在XAML中声明类型列表

时间:2012-08-16 09:16:03

标签: wpf xaml ivalueconverter

我正在使用一个值转换器,它需要获取类型列表,这是转换器的属性。如果我使用double值列表,我可以使用以下语法(按预期工作):

代码

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语法错误但我找不到合适的语法。

2 个答案:

答案 0 :(得分:2)

看起来像XAML设计师中的bug。给定的波纹管代码对我有用。我可以构建和运行应用程序。但是在设计师R#中使用系统:类型两行,设计师崩溃,每行有两个错误:

  

错误1 类型“类型”不能用作对象元素,因为它是   不公开或不定义公共无参数构造函数或   型转换器。
  错误2 “类型”类型不支持直接   内容。   因此,当我在之前尝试过该解决方案之前(在给出之前的解决方案之前),我认为我做错了。   但是编译器仍然没有给构建带来任何错误。无论如何它看起来如何:

<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 类是 abstract 。 希望它有所帮助

答案 1 :(得分:1)

好的,下面的例子编译并运行....我看到转换器被调用,列表中填充了2个Type对象。可能有更好的方法。


以下是我使用的完整代码:

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>