Hvordan binde en avmerkingsboks til en bool skrev DbColumn som kan ha nullverdier?

stemmer
4

I Windows Forms (.NET 2.0, Visual Studio 2005 SP1): Jeg har en skrevet DataSet, med en kolonne som type er System.Boolean, som kan ha nullverdier og som standardverdi er DBNull. Jeg har en Form, inneholdende en CheckBoxkontroll som jeg ønsker å binde seg til den tidligere kolonneverdi.

  • Jeg har forsøkt å binde Checkedeiendom til kolonnen via designeren: det fungerer bra, hvis standardverdien for kolonnen er satt til enten Trueeller False.
  • Jeg har forsøkt å binde CheckStateeiendom til kolonnen via designer, og feste mine egne Formatog Parseevent handlers, men de aldri bli kalt:

    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
    };
    
  • Jeg har forsøkt å lage en egendefinert Bindingeksempel i koden, legge mine hendelsesbehandlinger og legge den til de CheckBoxbindingene: hendelses handlers er likevel aldri bli kalt ...

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

Som et notat: en DBNullverdi er akseptabelt bare når kommer fra DataSet(det betyr at verdien har aldri satt). Men brukeren bør bare være i stand til å sette verdien til Trueeller Falsevia CheckBox.

For referanse, her er koden for parsing og formatering metoder:

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;
}
Publisert på 13/08/2009 klokken 13:52
kilden bruker
På andre språk...                            


2 svar

stemmer
1

Den easist måten jeg vet, er avledet fra avmerkingsbokser klassen, legge til "dataverdi" eiendom som kan håndtere DBNull verdier og binde data til "dataverdi" eiendom:

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;
            }
        }
    }
}
Svarte 18/08/2009 kl. 06:58
kilden bruker

stemmer
7

Har du prøvd å binde CheckBox.CheckState til DataColumn uten feste til å analysere og Format hendelser eller rote med innbindings?

Dessverre har jeg ikke har en forekomst av Visual Studio 2005 tilgjengelig, men jeg satt sammen en rask form i Visual Studio 2008, og det gjorde nøyaktig hva du har angitt:

Som et notat: en DBNull verdi er akseptabelt kun når kommer fra datasett (det betyr at verdien har aldri satt). Men brukeren bør bare være i stand til å sette verdien til Sant eller usant via sjekkheftet.

Jeg kan være Parse, format eller Binding komme i veien, eller det kan være at Windows Forms oppfører seg annerledes i 2008 enn i 2005


UPDATE 18 august: Det fungerer på Visual Studio 2005 for både gjennom designer og gjennom koden. Her er koden som demonstrerer det fungerer:


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

Hvorfor det fungerer

Bindingen har en egen metode som kalles FormatObject som er ansvarlig for å oppnå en representasjon av verdien som kommer fra datakilden som er egnet for å bli vist på kontrollen.

Når formateringen er aktivert, Binding.FormatObject () vil kjøre gjennom en kode bane som vil kalle eventuelle handlers du har for Binding.Format hendelsen. Dersom ingen behandler endrer verdien som forplantes fra datakilden til styre gjennom ConvertEventArgs.Value, vil denne verdien bli brukt. Ellers vil det ringe en standard formaterings kalt FormatObject på en intern klasse kalt System.Windows.Forms.Formatter.

Kommentarene på kildekoden tilstand:

“Den virkelige ombygging skjer inne FormatObjectInternal ()”

Kommentarene til FormatObjectInternal tilstand:

“Utfører noen spesielle case konverteringer (f.eks. Boolsk til check)”

Innsiden av FormatObjectInternal den sjekker for å se om verdien kommer fra datakilden er null eller DBNull og hvis det er tilfelle, det sjekker for å se om den type eiendommen blir bundet er av check. Hvis det er tilfelle, returnerer den CheckState.Indeterminate.

Som du kan se, er dette en vanlig sak at det er en overraskelse det fungerte ikke på Windows Forms 1.x. Heldigvis fikset det på 2,0 og utover.

Svarte 18/08/2009 kl. 10:25
kilden bruker

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