4

タイプが定義したクラスであるプロパティを持つユーザー コントロールを作成しようとしています。TypeConverterプロパティを文字列として処理できるようにするためにa を使用しています。アプリケーションは、プロパティが文字列の XAML の読み取りを正しく処理しますが、プロパティ パネルでプロパティが文字列に設定されている場合、XAML にはユーザー定義クラスを分割する拡張構文が含まれます。

具体的には、ちょっとわかりにくかったので、このマイクロソフトのチュートリアルに従っています。結果として、次のコードがあります。

Complex.cs

namespace WpfApplication1
{
    [TypeConverter(typeof(ComplexTypeConverter))]
    public class Complex
    {
        private double m_real;
        private double m_imag;

        public Complex() { }
        public Complex(double r, double i)
        {
            m_real = r;
            m_imag = i;
        }

        public double Real
        {
            get { return m_real; }
            set { m_real = value; }
        }

        public double Imaginary
        {
            get { return m_imag; }
            set { m_imag = value; }
        }

        public override string ToString()
        {
            return String.Format("{0},{1}", this.m_real, this.m_imag);
        }

        public static Complex Parse(string complexNumber)
        {
            if (String.IsNullOrEmpty(complexNumber))
            {
                return new Complex();
            }

            // The parts array holds the real and 
            // imaginary parts of the object.
            string[] parts = complexNumber.Split(',');
            return new Complex(double.Parse(parts[0].Trim()), double.Parse(parts[1].Trim()));
        }
    }

    public class ComplexTypeConverter : TypeConverter
    {
        private static List<Complex> defaultValues = new List<Complex>();

        static ComplexTypeConverter()
        {
            defaultValues.Add(new Complex(0, 0));
            defaultValues.Add(new Complex(1, 1));
            defaultValues.Add(new Complex(-1, 1));
            defaultValues.Add(new Complex(-1, -1));
            defaultValues.Add(new Complex(1, -1));
        }

        // Override CanConvertFrom to return true for String-to-Complex conversions.
        public override bool CanConvertFrom(
            ITypeDescriptorContext context,
            Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }

            return base.CanConvertFrom(context, sourceType);
        }

        // Override CanConvertTo to return true for Complex-to-String conversions.
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return true;
            }

            return base.CanConvertTo(context, destinationType);
        }

        // Override ConvertFrom to convert from a string to an instance of Complex.
        public override object ConvertFrom(
            ITypeDescriptorContext context,
            System.Globalization.CultureInfo culture,
            object value)
        {
            string text = value as string;

            if (text != null)
                            return Complex.Parse(text);                 

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

        // Override ConvertTo to convert from an instance of Complex to string.
        public override object ConvertTo(
            ITypeDescriptorContext context,
            System.Globalization.CultureInfo culture,
            object value,
            Type destinationType)
        {
            if (destinationType == null)
            {
                throw new ArgumentNullException("destinationType");
            }

            //Convert Complex to a string in a standard format.
            Complex c = value as Complex;

            if (c != null && this.CanConvertTo(context, destinationType))
            {
                return c.ToString();
            }

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

        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }

        public override TypeConverter.StandardValuesCollection GetStandardValues(
            ITypeDescriptorContext context)
        {
            StandardValuesCollection svc = new StandardValuesCollection(defaultValues);
            return svc;
        }
    }
}

ComplexNumberControl.xaml.cs

namespace WpfApplication1
{
    public partial class ComplexNumberControl : UserControl
    {
        public ComplexNumberControl()
        {
            InitializeComponent();
        }

        public Complex ComplexNumber
        {
            get
            {
                return (Complex)this.GetValue(ComplexNumberProperty);
            }

            set
            {
                this.SetValue(ComplexNumberProperty, value);
            }
        }

        public static readonly DependencyProperty ComplexNumberProperty = DependencyProperty.Register(
          "ComplexNumber",
          typeof(Complex),
          typeof(ComplexNumberControl),
          new PropertyMetadata(new Complex()));
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WpfApplication1">
    <Grid>
        <my:ComplexNumberControl HorizontalAlignment="Left" Margin="88,78,0,0" x:Name="complexNumberControl1" VerticalAlignment="Top" />
    </Grid>
</Window>

ComplexNumber="0,0"エラーなしでに追加できComplexNumberControlます (より複雑なアセンブリから、プロパティが複素数 0 + 0i として正しく処理されることがわかります)。ComplexNumberただし、プロパティ パネルで編集すると、XAML は次のように変更されます。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WpfApplication1">
    <Grid>
        <my:ComplexNumberControl HorizontalAlignment="Left" Margin="88,78,0,0" x:Name="complexNumberControl1" VerticalAlignment="Top">
            <my:ComplexNumberControl.ComplexNumber>
                <my:Complex Imaginary="-1" Real="1" />
            </my:ComplexNumberControl.ComplexNumber>
        </my:ComplexNumberControl>
    </Grid>
</Window>

ComplexNumber="1,-1"生成された XAMLが、詳細な構造体ではなく、単純に読み取るようにするにはどうすればよいComplexNumberControl.ComplexNumberですか?

4

1 に答える 1

2

ほぼそこにあり、期待どおりに機能させるには、 Complexクラスを2 つだけ微調整する必要があります。

1) デフォルトのパブリック コンストラクターを削除します。

public Complex() { } // <- delete this line

2) 魔法のDesignerSerializationVisibility属性をRealおよびImaginaryプロパティに追加します (または一般的には、パブリック セッターを持つすべてのプロパティに):

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double Real
{
    get { return m_real; }
    set { m_real = value; }
}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double Imaginary
{
    get { return m_imag; }
    set { m_imag = value; }
}

お役に立てれば。

于 2013-07-11T23:57:27.867 に答える