Как привязать CheckBox к BOOL типизированных DbColumn, который обнуляемый?

голоса
4

В Windows Forms (.NET 2.0, Visual Studio 2005 SP1): Я типизированный DataSet, с колонкой , какой тип System.Boolean, который обнуляемым и какое значение по умолчанию DBNull. У меня есть Form, содержащий CheckBoxэлемент управления , который я хочу , чтобы привязать к значению предыдущего столбца.

  • Я пытался связать Checkedсвойство столбца через конструктора: он прекрасно работает, только если значение по умолчанию для столбца устанавливается либо Trueили False.
  • Я пытался связать CheckStateсвойство столбца с помощью конструктора, и приложив свои собственные Formatи Parseобработчик событий , но они никогда не дозвонились:

    b.Format+=delegate(object sender, ConvertEventArgs cevent) {
        cevent.Value=DoFormat((CheckState)cevent.Value); // cf. end of the question
    };
    b.Parse+=delegate(object sender, ConvertEventArgs cevent) {
        cevent.Value=DoParse(cevent.Value); // cf. end of the question
    };
    
  • Я пытался создать пользовательский Bindingэкземпляр в коде, приложите свои обработчики событий и добавить его в CheckBoxпереплетах: обработчики событий никогда еще никогда не дозвонились ...

    Binding b=new Binding(CheckState, _BindingSource, MyColumn, false, DataSourceUpdateMode.OnPropertyChanged, DBNull.Value);
    

Как примечание: DBNullзначение приемлемо только тогда , когда исходит от DataSet(это означает , что значение никогда не был установлен). Но пользователь должен только быть в состоянии установить значение Trueили с Falseпомощью CheckBox.

Для справки, вот код синтаксического анализа и форматирования методов:

internal static CheckState DoParse(object value)
{
    if ((value==null) || (value is DBNull))
        return CheckState.Indeterminate;

    bool v=Convert.ToBoolean(value);
    return (v ? CheckState.Checked : CheckState.Unchecked);
}

internal static object DoFormat(CheckState value)
{
    switch (value)
    {
    case CheckState.Checked:
        return true;
    case CheckState.Indeterminate:
        return DBNull.Value;
    case CheckState.Unchecked:
        return false;
    }

    return null;
}
Задан 13/08/2009 в 14:52
источник пользователем
На других языках...                            


2 ответов

голоса
1

Лёгкий способом я знаю, проистекает из класса CheckBox, добавьте свойство «DataValue», который может обрабатывать значения DBNull и привязки данных к свойству «DataValue»:

public class DataCheckBox : CheckBox {
    public virtual object DataValue {
        get { return this.Checked; }
        set {
            if ( value == null || value is DBNull ) {
                this.CheckState = CheckState.Indeterminate;
            }
            else {
                this.Checked = (bool)value;
            }
        }
    }
}
Ответил 18/08/2009 в 07:58
источник пользователем

голоса
7

Вы пробовали связывание CheckBox.CheckState к DataColumn без прикрепления к Разобрать и формат событие или баловаться с Binding?

К сожалению , у меня нет экземпляра Visual Studio 2005 доступны , но я собрал быстрый формы в Visual Studio 2008 , и это было именно то , что вы указали:

Как примечание: значение DBNull допустимо только тогда, когда приходит из DataSet (это означает, что значение никогда не было установлено). Но пользователь должен только быть в состоянии установить значение Истина или Ложь через CheckBox.

Может быть, я Анализировать, формат или Binding получить на вашем пути, или это может быть, что Windows Forms ведет себя по-разному в 2008 году, чем в 2005 году


UPDATE 18 августа: Он работает на Visual Studio 2005 также и через конструктор и через код. Вот код , который демонстрирует его работать:


using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        DataTable table = new DataTable();
        public Form1() {
            InitializeComponent();

            //Creates the table structure
            table.Columns.Add("Name", typeof(string));
            table.Columns.Add("MyColumn", typeof(bool));

            //Populates the table with some stuff
            for (int i = 0; i < 5; i++) {
                table.Rows.Add(i.ToString());
            }

            //Creates the controls and puts them on the form.
            TextBox textBox = new TextBox();
            textBox.Location = new Point(10, 10);
            textBox.DataBindings.Add("Text", table, "Name");

            CheckBox checkBox = new CheckBox();
            checkBox.Left = textBox.Left;
            checkBox.Top = textBox.Bottom + 10;

            //Without true on the last argument, it will not work properly.
            checkBox.DataBindings.Add("CheckState", table, "MyColumn", true);

            Button previous = new Button();
            previous.Text = "";
            next.Top = previous.Top;
            next.Left = previous.Right + 5;
            next.Click += new EventHandler(next_Click);

            this.Controls.AddRange(new Control[] { textBox, checkBox, previous, next });
        }

        void next_Click(object sender, EventArgs e) {
            this.BindingContext[this.table].Position++;
        }

        void previous_Click(object sender, EventArgs e) {
            this.BindingContext[this.table].Position--;
        }
    }
}


UPDATE 23 августа:

Почему это работает

Связывание имеет частный метод, называемый FormatObject, который отвечает за получение представления значения, поступающее из источника данных, который подходит для показываются на контроле.

При форматировании включено, Binding.FormatObject () будет проходить через путь кода, который будет вызывать возможные обработчики у вас есть для случая Binding.Format. Если какой-либо обработчик изменяет значение, распространяющееся от источника данных к элементу управления через ConvertEventArgs.Value, будет использоваться это значение. В противном случае, он будет вызывать форматировщик по умолчанию под названием FormatObject на внутренний класс под названием System.Windows.Forms.Formatter.

Замечания о состоянии исходного кода:

«Реальная работа преобразование происходит внутри FormatObjectInternal ()»

Комментарии для FormatObjectInternal государства:

«Выполняет некоторые преобразования специального регистра (например, Boolean для CheckState)»

Внутри FormatObjectInternal он проверяет, является ли значение исходя из источника данных, является нулевым или DBNull, и если это так, то он проверяет, является ли тип объекта привязки имеет CheckState. Если это так, то он возвращает CheckState.Indeterminate.

Как вы можете видеть, это такой общий случай, что это удивительно, что не работает на Windows Forms 1.x. К счастью, закрепив его на 2,0 и за его пределами.

Ответил 18/08/2009 в 11:25
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more