Click here to Skip to main content
15,887,464 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
Hello folks.
I'm trying to write simple user control with three radio buttons that support data binding to bit (or bool) field. The three values for radio buttons are: "Yes" for true, "No" for false and "n/d" for null. For binding I've tried to use [System.ComponentModel.DefaultBindingProperty("Checked")] attribute but it's working one way only (reading from data source), or seems not to change anything at all.
The second thing is using INotifyPropertyChange interface for notification that my bool-binded property has changed, so control should update interface. But I don't quite understand, how to employ PropertyChangedEventHandler (am I missing some delegate?)
Below is the code for my control (except from designer, which is obvious).
Can anyone, please, just hit me with a hint, what am I missing here?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace TriStateRadioControlLibrary
{
    [System.ComponentModel.DefaultBindingProperty("Checked")] //simple binding attribute
    public partial class TriStateRadio : UserControl, INotifyPropertyChanged
    {
        // properties for external access
        public String TextTrueRadio { get { return radioButton1.Text; } set { radioButton1.Text = value; } }
        public String TextFalseRadio { get { return radioButton2.Text; } set { radioButton2.Text = value; } }
        public String TextNullRadio { get { return radioButton3.Text; } set { radioButton3.Text = value; } }

        public Nullable<bool> _checked;
        // binding property
        public Nullable<bool> Checked
        {
            get { return _checked; }
            set
            {
                if (value != _checked)
                {
                    _checked = value;
                    OnPropertyChanged("Checked");
                }
            }
        }

        private void CheckChanged() //instead of using stupid events, but working one way only
        {
            switch (_checked)
            {
                case true:
                    radioButton1.Checked = true;
                    break;
                case false:
                    radioButton2.Checked = true;
                    break;
                case null:
                    radioButton3.Checked = true;
                    break;
                default:
                    throw new Exception("Error selecting TriStateRadio state!");
                    //break;
            }
        }



        public TriStateRadio()
        {
            InitializeComponent();
        }

        //events for changing between radio buttons
        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioButton1.Checked == true)
            {
                this.Checked = true;
            }
        }

        private void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioButton2.Checked == true)
            {
                this.Checked = false;
            }
        }

        private void radioButton3_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioButton3.Checked == true)
            {
                this.Checked = null;
            }
        }


        #region PropertyChangeNotification
        protected void OnPropertyChanged(PropertyChangedEventArgs e)
        {

            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, e);
        }

        public void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

    }
}



I've been googling and debugging for hours now with no effect :(
Posted

1 solution

OK, I've solved both of my problems - with binded value not saved to data source and with not updating interface. The solution which I came is rather simple, but I still don't understand how INotifyPropertyChange interface is working. Below full, working solution with additional two methods.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace TriStateRadioControlLibrary
{
    [System.ComponentModel.DefaultBindingProperty("Checked")] //simple binding attribute
    public partial class TriStateRadio : UserControl, INotifyPropertyChanged
    {
        // properties for external access
        public String TextTrueRadio { get { return radioButton1.Text; } set { radioButton1.Text = value; } }
        public String TextFalseRadio { get { return radioButton2.Text; } set { radioButton2.Text = value; } }
        public String TextNullRadio { get { return radioButton3.Text; } set { radioButton3.Text = value; } }

        public Nullable<bool> _checked;
        // binding property
        public Nullable<bool> Checked
        {
            get { return _checked; }
            set
            {
                if (value != _checked)
                {
                    _checked = value;
                    OnPropertyChanged("Checked");
                }
            }
        }

        private void CheckChanged() //update bool field
        {
            switch (_checked)
            {
                case true:
                    radioButton1.Checked = true;
                    break;
                case false:
                    radioButton2.Checked = true;
                    break;
                case null:
                    radioButton3.Checked = true;
                    break;
                default:
                    throw new Exception("Error selecting TriStateRadio state!");
                    //break;
            }
        }



        public TriStateRadio()
        {
            InitializeComponent();
        }

        //events for changing between radio buttons
        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioButton1.Checked == true)
            {
                this.Checked = true;
            }
        }

        private void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioButton2.Checked == true)
            {
                this.Checked = false;
            }
        }

        private void radioButton3_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioButton3.Checked == true)
            {
                this.Checked = null;
            }
        }


        #region PropertyChangeNotification
        protected void OnPropertyChanged(PropertyChangedEventArgs e)
        {

            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, e);
        }

        public void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        
        public event PropertyChangedEventHandler PropertyChanged;
        
        #endregion

        //necesary to update control interface when loaded
        private void TriStateRadio_Load(object sender, EventArgs e)
        {
            PropertyChanged += new PropertyChangedEventHandler(TriStateRadio_PropertyChanged);
            CheckChanged();
        }

        void TriStateRadio_PropertyChanged(object sender, EventArgs e)
        {
            CheckChanged(); //this can be used with EventArgs to detect which property has actually changed
        }

    }
}

As I thought, it was the missing delegate :)
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900