This is a migrated thread and some comments may be shown as answers.

Special Days to Calendar Cell backcolor

14 Answers 303 Views
Calendar, DateTimePicker, TimePicker and Clock
This is a migrated thread and some comments may be shown as answers.
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
DoomerDGR8 asked on 01 Feb 2011, 04:58 PM
Hi. I'm reading a set of dates from DB and based on the scenario, I've come-up with this:

private void LoadLocumDiary() {
  foreach (Availability AvailabilityL in DbContext.Availabilities.Where(avail=> avail.LocumID == LocumID).OrderBy(date=>date.AvailableDate)) {
    RadCalendarDay sday = null;
 
    switch (AvailabilityL.AvailabilityStatusID) {
      case 1: //Available
      sday = new RadCalendarDay(AvailabilityL.AvailableDate) {
        Disabled = false,
        Selectable = true,
        ToolTip = AvailabilityL.AvailabilityStatus.Name
      };
      sday.TemplateItem.BackColor = Color.Green;
      break;
 
      case 2: //Unavailable
      sday = new RadCalendarDay(AvailabilityL.AvailableDate) {
        Disabled = false,
        Selectable = true,
        ToolTip = AvailabilityL.AvailabilityStatus.Name
      };
      sday.TemplateItem.BackColor = Color.Red;
      break;
 
      case 3: //On Job
      sday = new RadCalendarDay(AvailabilityL.AvailableDate) {
        Disabled = false,
        Selectable = true,
        ToolTip = AvailabilityL.AvailabilityStatus.Name
      };
      sday.TemplateItem.BackColor = Color.Goldenrod;
      break;
 
      default: break;
    }
 
    CalendarDiary.SpecialDays.Add(sday);
  }
 
 // CalendarDiary.InvalidateCalendar();
}

Now, I'm getting a null exception on sday.TemplateItem. What am I doing wrong. i need to set a tooltip and a back color on a day-cell.

14 Answers, 1 is accepted

Sort by
0
Accepted
Richard Slade
Top achievements
Rank 2
answered on 01 Feb 2011, 06:07 PM
Hi again Hassan,

To change the back colour, you'll need to use the ElementRender event (much like the cell formatting event in the RadGridView) .
The template item is null because it is a RadHostItem, and one is not contained in this instance.

Have a look at this documentation which explains the important events in the radCalendar.

Hope that helps
Richard
0
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
answered on 02 Feb 2011, 10:00 AM
Excellent answer. The links in the documentation are broken though. More importantly, if I subscribe the RenderElement event, how will I force the calendar to redraw or refresh so that it'll call the event again AFTER i made changes to the under-lying DB?
0
Richard Slade
Top achievements
Rank 2
answered on 02 Feb 2011, 10:42 AM
Hi Hassan,

I think in your situation you would just call RadCalendar1.Update(); though I'd need to see an exmaple to try this out. Give it a go, and if you find you need further help, then just let me know.
Regards,
Richard
0
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
answered on 03 Feb 2011, 04:36 PM
okay, the ElementRender event is fired just too many times. Even on selecting a day the UI hangs as it goes through my checks in the event. Can't i access the RadCalendarDay and the LightVisualElement some other way? My new strategy is to have my days customized whenever i want to manually.

Here is what I'm trying to achieve:

private void CalendarDiary_ElementRender(object sender, RenderElementEventArgs e) {
  if (e.Day.Date < DateTime.Now.Date) {
    return;
  }
 
  Cursor.Current = Cursors.WaitCursor;
 
  foreach (Availability AvailabilityL in ConcernedAvailabilities.Where(avail => avail.AvailableDate == e.Day.Date)) {
    switch (AvailabilityL.AvailabilityStatusID) {
      case 1: //Available
      e.Day.ToolTip = e.Element.ToolTipText = "Available";
      e.Element.BackColor = Color.FromArgb(177, 243, 177);
      e.Element.BackColor2 = Color.LimeGreen;
      e.Element.BackColor3 = Color.LimeGreen;
      e.Element.BackColor4 = Color.LimeGreen;
 
      e.Element.BorderColor = Color.Black;
      e.Element.BorderWidth = 1;
      break;
 
      case 2: //Unavailable
      e.Day.ToolTip = e.Element.ToolTipText = "Unavailable";
      e.Element.BackColor = Color.FromArgb(255, 218, 224);
      e.Element.BackColor2 = Color.LightPink;
      e.Element.BackColor3 = Color.LightPink;
      e.Element.BackColor4 = Color.LightPink;
 
      e.Element.BorderColor = Color.Black;
      e.Element.BorderWidth = 1;
      break;
 
      case 3: //On Job
      e.Day.ToolTip = e.Element.ToolTipText = "On Job";
      e.Element.BackColor = Color.FromArgb(248, 242, 198);
      e.Element.BackColor2 = Color.Khaki;
      e.Element.BackColor3 = Color.Khaki;
      e.Element.BackColor4 = Color.Khaki;          
 
      e.Element.BorderColor = Color.Black;
      e.Element.BorderWidth = 1;
      break;
 
      case 4: //Holiday
      e.Day.ToolTip = e.Element.ToolTipText = "On Holiday";
      e.Element.BackColor = Color.FromArgb(222, 239, 245);
      e.Element.BackColor2 = Color.LightBlue;
      e.Element.BackColor3 = Color.LightBlue;
      e.Element.BackColor4 = Color.LightBlue;
 
      e.Element.BorderColor = Color.Black;
      e.Element.BorderWidth = 1;
      break;
 
      default: break;
    }
  }
 
  Cursor.Current = Cursors.Default;
}
0
Richard Slade
Top achievements
Rank 2
answered on 03 Feb 2011, 05:31 PM
Hi,

There is another way to loop over the cells in the calendar. You would need to do this each time the calendar changes month to check for special days and colour them .

CalendarTableElement table = (CalendarTableElement)this.RadCalendar1.CalendarElement.CalendarVisualElement.Children[0].Children[1];
foreach (CalendarCellElement cell in table.Children) {
    if (cell.SpecialDay) {
        switch (true) {
            case cell.Date == Today:
                cell.BackColor = Color.Blue;
                cell.NumberOfColors = 1;
                break;
            case cell.Date == Today.AddDays(1):
                cell.BackColor = Color.Green;
                cell.NumberOfColors = 1;
                break;
            case cell.Date == Today.AddDays(2):
                cell.BackColor = Color.Pink;
                cell.NumberOfColors = 1;
                break;
        }
    }
}

Let me know if that helps
Richard
0
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
answered on 04 Feb 2011, 12:56 PM
I still stuck with this...

here is what I have so far:

private void CustomPainting() {
  CalendarTableElement table = (CalendarTableElement)CalendarDiary.CalendarElement.CalendarVisualElement.Children[0].Children[1];
  var req = table.Children; //.Where(x => x is CalendarCellElement);
 
  foreach (CalendarCellElement cell in req) {
 
    if (ConcernedAvailabilities.Any(avail => avail.AvailableDate.Date == cell.Date.Date)) {
      Availability AvailabilityL = ConcernedAvailabilities.FirstOrDefault(avail => avail.AvailableDate.Date == cell.Date.Date);
 
      switch (AvailabilityL.AvailabilityStatusID) {
        case 1: //Available
        cell.ToolTipText = "Available";
        cell.BackColor = Color.FromArgb(177, 243, 177);
        cell.NumberOfColors = 1;
        cell.BorderColor = Color.Black;
        cell.BorderWidth = 1;
        break;
 
        case 2: //Unavailable
        cell.ToolTipText = "Unavailable";
        cell.BackColor = Color.FromArgb(255, 218, 224);
        cell.NumberOfColors = 1;
        cell.BorderColor = Color.Black;
        cell.BorderWidth = 1;
        break;
 
        case 4: //Holiday
        cell.ToolTipText = "Holiday";
        cell.BackColor = Color.FromArgb(222, 239, 245);
        cell.NumberOfColors = 1;
        cell.BorderColor = Color.Black;
        cell.BorderWidth = 1;
        break;
 
        case 3: //On Job
        cell.ToolTipText = "On Job";
        cell.BackColor = Color.FromArgb(248, 242, 198);
        cell.NumberOfColors = 1;
        cell.BorderColor = Color.Black;
        cell.BorderWidth = 1;
        break;
 
        default: break;
      }
    }
  }
 
}

Now, thetable.Children returns four items and they are the four multiview calendars I'm using... what can I do now?
0
Accepted
Richard Slade
Top achievements
Rank 2
answered on 04 Feb 2011, 01:26 PM
Hello Hassan,

If I understand you correctly, then you'd need to create an outer loop, to loop over the 4 calendars that are contained within the table.Children.
Hope that helps
Richard
0
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
answered on 04 Feb 2011, 01:35 PM
Did that bit.

The outer for-each is like this now:

private void CustomPainting() {
  CalendarTableElement table = (CalendarTableElement)CalendarDiary.CalendarElement.CalendarVisualElement.Children[0].Children[1];
  var req = table.Children.Where(x => x is MonthViewElement);
 
  foreach (MonthViewElement cell in req) {
 
    if (ConcernedAvailabilities.Any(avail => avail.AvailableDate.Date == cell.Date.Date)) {
      Availability AvailabilityL = ConcernedAvailabilities.FirstOrDefault(avail => avail.AvailableDate.Date == cell.Date.Date);
 
      switch (AvailabilityL.AvailabilityStatusID) {
        case 1: //Available
        cell.ToolTipText = "Available";
        cell.BackColor = Color.FromArgb(177, 243, 177);
        cell.NumberOfColors = 1;
        cell.BorderColor = Color.Black;
        cell.BorderWidth = 1;
        break;
 
        case 2: //Unavailable
        cell.ToolTipText = "Unavailable";
        cell.BackColor = Color.FromArgb(255, 218, 224);
        cell.NumberOfColors = 1;
        cell.BorderColor = Color.Black;
        cell.BorderWidth = 1;
        break;
 
        case 4: //Holiday
        cell.ToolTipText = "Holiday";
        cell.BackColor = Color.FromArgb(222, 239, 245);
        cell.NumberOfColors = 1;
        cell.BorderColor = Color.Black;
        cell.BorderWidth = 1;
        break;
 
        case 3: //On Job
        cell.ToolTipText = "On Job";
        cell.BackColor = Color.FromArgb(248, 242, 198);
        cell.NumberOfColors = 1;
        cell.BorderColor = Color.Black;
        cell.BorderWidth = 1;
        break;
 
        default: break;
      }
    }
  }
 
}

what will be the inner loop like?
0
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
answered on 04 Feb 2011, 03:15 PM
Okay, I figured the outer and the inner loops as follows:

private void CustomPainting() {
  Cursor.Current = Cursors.WaitCursor;
 
  foreach (MonthViewElement currentMonthViewElement  in CalendarDiary.RootElement.Children[0].Children[0].Children[2].Children[0].Children[1].Children) {
    CalendarTableElement table = (CalendarTableElement)currentMonthViewElement.Children[0].Children[1];
 
    foreach (CalendarCellElement cell in table.Children) {
      if (ConcernedAvailabilities.Any(avail => avail.AvailableDate.Date == cell.Date.Date)) {
        Availability AvailabilityL = ConcernedAvailabilities.FirstOrDefault(avail => avail.AvailableDate.Date == cell.Date.Date);
 
        switch (AvailabilityL.AvailabilityStatusID) {
          case 1: //Available
          cell.ToolTipText = "Available";
          cell.BackColor = Color.FromArgb(177, 243, 177);
          cell.NumberOfColors = 1;
          cell.BorderColor = Color.Black;
          cell.BorderWidth = 1;
          break;
 
          case 2: //Unavailable
          cell.ToolTipText = "Unavailable";
          cell.BackColor = Color.FromArgb(255, 218, 224);
          cell.NumberOfColors = 1;
          cell.BorderColor = Color.Black;
          cell.BorderWidth = 1;
          break;
 
          case 4: //Holiday
          cell.ToolTipText = "Holiday";
          cell.BackColor = Color.FromArgb(222, 239, 245);
          cell.NumberOfColors = 1;
          cell.BorderColor = Color.Black;
          cell.BorderWidth = 1;
          break;
 
          case 3: //On Job
          cell.ToolTipText = "On Job";
          cell.BackColor = Color.FromArgb(248, 242, 198);
          cell.NumberOfColors = 1;
          cell.BorderColor = Color.Black;
          cell.BorderWidth = 1;
          break;
 
          default:
            break;
        }
 
        cell.Invalidate();
      }
    }
 
  }
 
  Cursor.Current = Cursors.Default;
}

Problem is, all cells are getting painted. The whole calendar is painted. Maybe i need to implement if-else and in the else, I need to re-set a cell's formatiing. How do I re-set to theme's default?
0
Accepted
Richard Slade
Top achievements
Rank 2
answered on 04 Feb 2011, 03:25 PM
Hi Hassan,

To reset a value, an exmaple (for back color) would be as followis

cell.ResetValue(LightVisualElement.BackColorProperty)

Hope that helps
Richard
0
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
answered on 04 Feb 2011, 04:03 PM
One last thing, handling the else part leaves the whole calender in a washed-out state as all rowheaders and column headers are also a CalendarCellElement. How can I find the DayCellElement only (if there is such a thing)?
0
Richard Slade
Top achievements
Rank 2
answered on 04 Feb 2011, 04:10 PM
Hi Hassan,

As you are looping though, you could just inspect the cell text to see if it's an integer (a day) as the headers will be M,T,W,T,F etc...
E.g.

Dim result As Integer = -1
If Integer.TryParse(cell.Text, result) Then
    Debug.WriteLine(result) ' It's a day cell
End If

Hope that helps
Richard
0
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
answered on 04 Feb 2011, 04:19 PM
Well, I actually started with that but after much brain hammering, I found a very simple and descent solution:

Final Code:

private void CustomPainting() {
  Cursor.Current = Cursors.WaitCursor;
 
  foreach (MonthViewElement currentMonthViewElement  in CalendarDiary.RootElement.Children[0].Children[0].Children[2].Children[0].Children[1].Children) {
    var CalendarCellElements = ((CalendarTableElement)currentMonthViewElement.Children[0].Children[1]).Children.OfType < CalendarCellElement>();
    //var CalendarCellElements1 = CalendarCellElements.Where(x => x.Tag != null && x.Tag.ToString() == "xCell");
     
    foreach (CalendarCellElement cell in CalendarCellElements.Where(x=> x.Column>0 && x.Row>0)) {
       
      if (ConcernedAvailabilities.Any(avail => avail.AvailableDate.Date == cell.Date.Date)) {
        Availability AvailabilityL = ConcernedAvailabilities.FirstOrDefault(avail => avail.AvailableDate.Date == cell.Date.Date);
 
        switch (AvailabilityL.AvailabilityStatusID) {
          case 1: //Available
          cell.ToolTipText = "Available";
          cell.BackColor = Color.FromArgb(177, 243, 177);
          cell.NumberOfColors = 1;
          //cell.BorderColor = Color.Black;
          //cell.BorderWidth = 1;
          break;
 
          case 2: //Unavailable
          cell.ToolTipText = "Unavailable";
          cell.BackColor = Color.FromArgb(255, 218, 224);
          cell.NumberOfColors = 1;
          //cell.BorderColor = Color.Black;
          //cell.BorderWidth = 1;
          break;
 
          case 4: //Holiday
          cell.ToolTipText = "Holiday";
          cell.BackColor = Color.FromArgb(222, 239, 245);
          cell.NumberOfColors = 1;
          //cell.BorderColor = Color.Black;
          //cell.BorderWidth = 1;
          break;
 
          case 3: //On Job
          cell.ToolTipText = "On Job";
          cell.BackColor = Color.FromArgb(248, 242, 198);
          cell.NumberOfColors = 1;
          //cell.BorderColor = Color.Black;
          //cell.BorderWidth = 1;
          break;
 
          default:
          break;
        }
 
        cell.Invalidate();
 
      } else {           
        cell.ToolTipText = String.Empty;
        //cell.ResetValue(LightVisualElement.BorderWidthProperty);
        //cell.ResetValue(LightVisualElement.BorderColorProperty);
        cell.ResetValue(LightVisualElement.BackColorProperty);
        cell.ResetValue(LightVisualElement.NumberOfColorsProperty);
                     
        cell.Invalidate();
 
      }
    }
 
  }
 
  CalendarDiary.InvalidateCalendar();
 
  Cursor.Current = Cursors.Default;
}

Looking with Row and Column > 0 puts us in the actual day cells.
0
Richard Slade
Top achievements
Rank 2
answered on 04 Feb 2011, 04:37 PM
Glad you have it all sorted.
All the best
Richard
Tags
Calendar, DateTimePicker, TimePicker and Clock
Asked by
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
Richard Slade
Top achievements
Rank 2
DoomerDGR8
Top achievements
Rank 2
Iron
Iron
Iron
Share this question
or