Hoe maak je een checkbox om een ​​bool getypte DbColumn dat is nullable binden?

stemmen
4

In Windows Forms (.NET 2.0, Visual Studio 2005 SP1): Ik heb een getypt DataSet, met een kolom welk type is System.Boolean, dat is vernietigbaar en welke standaardwaarde is DBNull. Ik heb Formgemaakt met een CheckBoxcontrole die wil binden aan de waarde voorafgaande kolom.

  • Ik heb geprobeerd om het te binden Checkedwoning aan de kolom via de ontwerper: het werkt geweldig, alleen als de standaardwaarde voor de kolom is ingesteld op Trueof False.
  • Ik heb geprobeerd om het te binden CheckStatewoning aan de kolom via de ontwerper, en het bevestigen van mijn eigen Formaten Parseevent handlers maar ze nooit gecalled:

    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
    };
    
  • Ik heb geprobeerd om een aangepaste maken Bindingbijvoorbeeld in de code, bevestigt mijn event handlers toevoegen aan de CheckBoxbindingen: de event handlers nog nooit gecalled ...

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

Als een opmerking: een DBNullwaarde is alleen aanvaardbaar als je vanuit de DataSet(betekent dit dat de waarde is nooit ingesteld). Maar de gebruiker moet alleen in staat om de waarde op Trueof Falsevia het CheckBox.

Ter referentie, hier is de code van de parseer en opmaak methoden:

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;
}
De vraag is gesteld op 13/08/2009 om 14:52
bron van user
In andere talen...                            


2 antwoorden

stemmen
1

De easist manier die ik ken, is afgeleid van CheckBox klasse toe te voegen "DataValue" eigenschap die kan omgaan met DBNull waarden en de data te binden aan "DataValue" eigenschap:

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;
            }
        }
    }
}
antwoordde op 18/08/2009 om 07:58
bron van user

stemmen
7

Heb je geprobeerd te binden CheckBox.CheckState de DataColumn zonder daaraan te ontleden en te Format evenementen of knoeien met de Binding?

Helaas heb ik niet heb een exemplaar van Visual Studio 2005 beschikbaar, maar ik verzamelde snel een formulier in Visual Studio 2008 en het deed precies wat u hebt opgegeven:

Als een opmerking: een DBNull waarde is alleen aanvaardbaar wanneer je uit de dataset (betekent dit dat de waarde is nooit ingesteld). Maar de gebruiker moet alleen in staat zijn om de waarde op True of False ingesteld via de CheckBox.

Ik kan de Parse, formaat of Binding in de weg of het kan zijn dat Windows Forms gedraagt ​​zich anders in 2008 dan in 2005


UPDATE 18 augustus: Het werkt op Visual Studio 2005 ook zowel door de ontwerper en door middel van code. Hier is de code dat het aantoont werken:


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 augustus:

Waarom het werkt

Binding heeft een eigen methode genaamd formatObject die verantwoordelijk is voor het verkrijgen van een representatie van de waarde uit de gegevensbron die geschikt is voor de besturing getoond is.

Wanneer het formatteren is ingeschakeld, Binding.FormatObject () wordt uitgevoerd door middel van een code pad dat eventuele handlers je hebt voor de Binding.Format evenement zal roepen. Indien de waarde handler worden vermeerderd uit de gegevensbron met de besturing via ConvertEventArgs.Value verandert, wordt die waarde gebruikt. Anders zal het een standaard formatter genaamd formatObject op een intern klasse met de naam System.Windows.Forms.Formatter noemen.

De opmerkingen over de broncode staat:

“De echte verbouwing gebeurt in FormatObjectInternal ()”

Het commentaar bij FormatObjectInternal staat:

“Voert een aantal speciale geval conversies (bijv. Boolean aan CheckState)”

Binnenkant van FormatObjectInternal wordt gecontroleerd om te zien of de waarde uit de gegevensbron null of DBNull en als dat het geval is, controleert het om te zien of het type van het pand te zijn gebonden is CheckState. Als dat het geval is, is het resultaat CheckState.Indeterminate.

Zoals u kunt zien, dit is een dergelijk gemeenschappelijk geval dat het een verrassing dat het niet werkte op Windows Forms 1.x. Gelukkig, de vaste het op 2.0 en daarbuiten.

antwoordde op 18/08/2009 om 11:25
bron van user

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