WPF Visual Studio Designer 和 Expression Blend 不尊重 DependencyProperty 上的 TypeConverter

发布于 2024-08-30 04:49:11 字数 2537 浏览 0 评论 0原文

我已将依赖属性 MyList 添加到 wpf 文本框。依赖属性的类型为 List。为了使 xaml 中的事情变得更容易,我定义了一个转换器,以便可以具有以下语法:

<Grid>
    <controls:MyTextBox x:Name="Hello" MyList="One,Two" Text="Hello" />
</Grid>

在 Visual Studio 中,我根本无法编辑属性,在 Expression Blend 中,我可以键入字符串,但它会生成以下 xaml:

<controls:MyTextBox x:Name="Hello" Text="Hello" >
 <controls:MyTextBox.MyList>
  <System_Collections_Generic:List`1 Capacity="2">
   <System:String>One</System:String>
   <System:String>Two</System:String>
  </System_Collections_Generic:List`1>
 </controls:MyTextBox.MyList>
</controls:MyTextBox>

有什么想法可以在 Visual Studio 和 Blend 中将此属性编辑为字符串吗?

public class MyTextBox : TextBox
{
    [TypeConverter(typeof(MyConverter))]
    public List<string> MyList
    {
        get { return (List<string>)GetValue(MyListProperty); }
        set { SetValue(MyListProperty, value); }
    }

    public static readonly DependencyProperty MyListProperty = DependencyProperty.Register("MyList", typeof(List<string>), typeof(MyTextBox), new FrameworkPropertyMetadata(new List<string> { "one" }));
}


public class MyConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if(sourceType == typeof(string))
            return true;
        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if(value is string)
            return new List<string>(((string)value).Split(','));    

        return base.ConvertFrom(context, culture, value);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if(destinationType == typeof(string))
            return true;
        return base.CanConvertTo(context, destinationType);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if(destinationType == typeof(string))
        {
            var ret = string.Empty; 
            var s = ret;
            ((List<string>)value).ForEach(v => s += s + v + ",");
            ret = ret.Substring(0, ret.Length - 1);

            return ret;
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }
}

I have added the dependency property MyList to a wpf textbox. The dependency property is of type List<string>. In order to make things easier in xaml I have defined a converter so that I can have following syntax:

<Grid>
    <controls:MyTextBox x:Name="Hello" MyList="One,Two" Text="Hello" />
</Grid>

In Visual Studio I can't edit the property at all and in Expression Blend I can type in the string but it generates the following xaml:

<controls:MyTextBox x:Name="Hello" Text="Hello" >
 <controls:MyTextBox.MyList>
  <System_Collections_Generic:List`1 Capacity="2">
   <System:String>One</System:String>
   <System:String>Two</System:String>
  </System_Collections_Generic:List`1>
 </controls:MyTextBox.MyList>
</controls:MyTextBox>

Any ideas how I can just edit this property as a string in both Visual Studio and Blend??

public class MyTextBox : TextBox
{
    [TypeConverter(typeof(MyConverter))]
    public List<string> MyList
    {
        get { return (List<string>)GetValue(MyListProperty); }
        set { SetValue(MyListProperty, value); }
    }

    public static readonly DependencyProperty MyListProperty = DependencyProperty.Register("MyList", typeof(List<string>), typeof(MyTextBox), new FrameworkPropertyMetadata(new List<string> { "one" }));
}


public class MyConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if(sourceType == typeof(string))
            return true;
        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if(value is string)
            return new List<string>(((string)value).Split(','));    

        return base.ConvertFrom(context, culture, value);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if(destinationType == typeof(string))
            return true;
        return base.CanConvertTo(context, destinationType);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if(destinationType == typeof(string))
        {
            var ret = string.Empty; 
            var s = ret;
            ((List<string>)value).ForEach(v => s += s + v + ",");
            ret = ret.Substring(0, ret.Length - 1);

            return ret;
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

乖乖兔^ω^ 2024-09-06 04:49:11

使用泛型不可能做到这一点,VS 和 Blend 设计者在进行设计时序列化时都会使用这些标签生成集合信息。一种解决方法是为 MyList 而不是 List 创建您自己的数据类型。 :(

或者

您需要将 MyList 保留为 String 属性,然后解析后续字符串并将它们存储到列表中。

或者

还有一种可能的解决方案。[如果您之前知道列表的值]

而不是使用 ListList< string> 使其成为带有 Flags 的枚举,这样您就可以在 VS Designer 和 Blend 中获得预期的输出语法,而无需这些垃圾代码

there is no possibility for doing this with generics, both VS and Blend designers will generate the collection information with those tags while doing design-time serialization. One work around is to create your own data type for MyList instead of List. :(

Or

You need to keep the MyList as a String property then, parse subsequent strings and store them into a List.

Or

One more possible solution. [if you know the values of list earlier]

Instead of using a List<string> make it an enum with Flags. So, that you can get the expected output syntax in both VS Designer and Blend without those junk codes.

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文