Привязка данных Winforms: Можно ли использовать TypeConverter вместо событий Format / Parse? - PullRequest
6 голосов
/ 07 августа 2010

В форме Winforms я хочу предоставить визуальные подсказки пользователю, когда поле ввода содержит недопустимое значение. Для этого я хочу связать свойство ForeColor метки поля ввода со свойством (логическое значение) IsPropertyValid базовой модели, чтобы метка стала красной, когда IsPropertyValid == false.

В настоящее время у меня есть обработчик для события привязки Format:

Controls["dateOfBirthLabel"].DataBindings["ForeColor"].Format += convertBoolToColor;
// (dateOfBirthLabel.ForeColor is bound to a boolean IsDateOfBirthValid property.)

void convertBoolToColor(object sender, ConvertEventArgs e)
{
    e.Value = (bool)e.Value ? Color.Black : Color.Red;
}

Если бы я хотел сделать это в WPF, я бы предположил, что я бы указывал пользовательский преобразователь значений (bool до Color) напрямую с привязкой в ​​XAML. Самое главное, мне бы не пришлось ссылаться на конкретный элемент управления через его имя.

Я бы хотел сделать то же самое с моей формой Winforms. В идеале я мог бы указать объект TypeConverter для конкретной привязки непосредственно в конструкторе форм. Это возможно?

Ответы [ 2 ]

5 голосов
/ 14 августа 2015

Мой предыдущий ответ (теперь удаленный) был неверным: это можно сделать, используя пользовательский TypeConverter.

Во-первых, нужен подходящий конвертер. (В отличие от XAML, один не реализует IValueConverter, но является производным от TypeConverter.) Например:

// using System;
// using System.ComponentModel;
// using System.Drawing;
// using System.Globalization;

sealed class BooleanToColorConverter : TypeConverter
{
    public override bool CanConvertTo(ITypeDescriptorContext context,
                                      Type destinationType)
    {
        return destinationType == typeof(Color);
    }

    public override object ConvertTo(ITypeDescriptorContext context,
                                     CultureInfo culture,
                                     object value, 
                                     Type destinationType)
    {
        return (bool)value ? Color.Green : Color.Red;
    }
}

Далее (а также в отличие от привязки данных XAML) этот преобразователь не применяется к самой привязке ; он должен быть присоединен к свойству источника данных с помощью атрибута [TypeConverter] :

// using System.ComponentModel;

partial class DataSource : INotifyPropertyChanged
{
    [TypeConverter(typeof(BooleanToColorConverter))] // <-- add this! 
    public bool IsValid { get { … } set { … } }
}

Наконец, , форматирование должно быть включено для привязки данных:

// Control control = …;
// DataSource dataSource = …;

control.DataBindings.Add("ForeColor", dataSource, "IsValid", formattingEnabled: true);
//                                                           ^^^^^^^^^^^^^^^^^^^^^^^

Обратите внимание, что в этом примере рассматривается только односторонняя (источник данных для управления) привязка данных. Для двухсторонней привязки данных вам также необходимо переопределить методы TypeConverter.ConvertFrom и TypeConverter.CanConvertFrom.

0 голосов
/ 18 июня 2014
c.DataBindings.Add("Checked", dataSource, dataMember, true, DataSourceUpdateMode.OnPropertyChanged );


class Someclass
{
[TypeConverter(typeof(IntBoolConverter))]
        public int p_isEnable
        {
            get { return nc_isEnable; }
            set { m_isEnable= value); }
        }
}
 public class IntBoolConverter:TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {

            if (sourceType == typeof(bool))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }

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

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is bool)
            {
                var objectToInt = value.ObjectToBool();
                return objectToInt;
            }
            return base.ConvertFrom(context, culture, value);
        }
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(bool))
            {
                return value.ObjectToBool();
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }
...