Question

How do you perform databinding against the MonthCalendar.SelectionRange property? Given the property is of type 'SelectionRange' which is a class I am not sure how to go about it. Any examples would be much appreciated.

Was it helpful?

Solution

Well, there don't seem to be any obvious events for this either on the MonthCalendar or the SelectionRange, and neither implements INotifyPropertyChanged, so it looks like data-binding might not be possible here.

Update: It does, however, raise the DateChanged, so you could hook some stuff together manually, or (more usefully) by subclassing the control to expose the values and events in a fashion suitable for binding. Note the Actual(...) are useful because the end (otherwise) is just before midnight, rather than midnight itself...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Forms;
class Foo : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        Debug.WriteLine(ToString());
    }
    private void SetField<T>(ref T field, T value, string propertyName)
    {
        if (!EqualityComparer<T>.Default.Equals(field, value))
        {
            field = value;
            OnPropertyChanged(propertyName);            
        }
    }
    private DateTime start, end;
    public DateTime Start { get { return start; } set { SetField(ref start, value, "Start"); } }
    public DateTime End { get { return end; } set { SetField(ref end, value, "End"); } }
}

class BindableCalendar : MonthCalendar
{
    public DateTime ActualSelectionStart
    {
        get { return SelectionRange.Start; }
        set { if (ActualSelectionStart != value) { SetSelectionRange(value, ActualSelectionEnd); } }
    }
    public DateTime ActualSelectionEnd
    {
        get { return SelectionRange.End; }
        set { if (ActualSelectionEnd != value) { SetSelectionRange(ActualSelectionStart, value); } }
    }
    // should really use EventHandlerList here...
    public event EventHandler ActualSelectionStartChanged, ActualSelectionEndChanged;

    DateTime lastKnownStart, lastKnownEnd;
    protected override void OnDateChanged(DateRangeEventArgs drevent)
    {
        base.OnDateChanged(drevent);
        if (lastKnownStart != drevent.Start)
        {
            if (ActualSelectionStartChanged != null) ActualSelectionStartChanged(this, EventArgs.Empty);
            lastKnownStart = drevent.Start;
        }
        if (lastKnownEnd != drevent.End)
        {
            if (ActualSelectionEndChanged != null) ActualSelectionEndChanged(this, EventArgs.Empty);
            lastKnownEnd = drevent.End;
        }
    }

}

static class Program
{
    [STAThread]
    static void Main()
    {

        Application.EnableVisualStyles();
        MonthCalendar cal;
        Button btn;
        using (Form form = new Form
        {
            Controls = {
                (cal = new BindableCalendar { Dock = DockStyle.Fill, MaxSelectionCount = 10 }),
                (btn = new Button { Dock = DockStyle.Bottom, Text = "thwack"})
            }
        })
        {
            Foo foo = new Foo { Start = DateTime.Today, End = DateTime.Today.AddDays(1) };
            cal.DataBindings.Add("ActualSelectionStart", foo, "Start").DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
            cal.DataBindings.Add("ActualSelectionEnd", foo, "End").DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
            btn.Click += delegate
            {
                foo.Start = foo.Start.AddDays(1);
                foo.End = foo.End.AddDays(1);
            };
            Application.Run(form);
        }
    }
}

OTHER TIPS

For me it seems to be very simple. I just bound SelectionStart and SelectionEnd properties of the MonthCalendar component.

this.Calendar1.DataBindings.Add(new System.Windows.Forms.Binding("SelectionStart",
bindingSource, "DateField", true));
this.Calendar1.DataBindings.Add(new System.Windows.Forms.Binding("SelectionEnd",
bindingSource, "DateField", true));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top