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

Getting visible dates from RadCalendar

5 Answers 270 Views
Calendar, DateTimePicker, TimePicker and Clock
This is a migrated thread and some comments may be shown as answers.
Taylor
Top achievements
Rank 1
Taylor asked on 13 Feb 2012, 06:57 PM

I'm using Winforms 2011.3.11.1116.  I'm trying to position another control on top of a RadCalendar (a textbox) as part of a small WYSIWYG calendar-printing app.  I will position the textbox to fill the largest remaining space on the calendar--meaning the largest space on the calendar that does not contain any days from the focused month--, either at the top or bottom.  Of course, to do this, I need to be able to figure out WHERE the largest remaining space is.

I have the calendar in a 6 row month view, and I set ShowOtherMontDays to false. I have tried the following:

1) My first thought was to ask the DefaultView for the month and the first and last day shown in the view, then do the necessary calculations to figure out where the "space" was.  No go, because the ViewStartDate and ViewEndDate properties refer to the first and last day of the month (which I can figure out myself from the month), NOT the first and last element rendered.

2) Then I thought I should iterate through the elements, getting the dates and finding the min and max.  But ... there is no iterable collection that I can find. That was, to put it mildly, surprising.  (As it was in a related thread for a different technology:http://www.sitefinity.com/devnet/forums/sitefinity-3-x/general-discussions/radcalendar-search-date-and-bold-it.aspx ).

3) Next I thought to try a combination of Navigating and ElementRender. In Navigating, I would set a Min and Max date to a sentinel value, then in ElementRender I would find the min and max dates as they were rendered. However, for some odd reason, at least one date in the previous view is, at least sometimes, rendered after Navigating fires.  Though this is annoying, I could cache all the dates, then figure out which one was not like the others (say, sort the list, and find wherever there was a gap between dates).  But, there is also the problem of the initial view, which does not trigger the Navigating or Navigated events.

This seems much too complicated, to me, so I guessed that I was probably not thinking of the best way to solve this problem.

Thoughts?

5 Answers, 1 is accepted

Sort by
0
Accepted
Ivan Todorov
Telerik team
answered on 16 Feb 2012, 05:32 PM
Hello Brandon,

Thank you for contacting us.

There is a way to iterate all the elements and filter them so that you get only the needed elements. Here is a short sample of how you can manipulate the nested text box according to the position of the first date of the selected month:
public Form2()
{
    InitializeComponent();
     
    this.radCalendar1.AllowMultipleView = true;
    this.radCalendar1.Location = new System.Drawing.Point(13, 13);
    this.radCalendar1.MultiViewRows = 3;
    this.radCalendar1.Size = new System.Drawing.Size(254, 640);
     
    //text box is added to the radCalendar1's Controls collection
    this.radTextBox1.Location = new System.Drawing.Point(15, 68);
    this.radTextBox1.Size = new System.Drawing.Size(100, 20);
 
    this.radCalendar1.ViewChanged += new EventHandler(radCalendar1_ViewChanged);
}
 
void radCalendar1_ViewChanged(object sender, EventArgs e)
{
    this.radCalendar1.Invalidate();
    List<RadElement> list = this.radCalendar1.CalendarElement.GetDescendants(x => x is CalendarCellElement, Telerik.WinControls.TreeTraversalMode.BreadthFirst);
    foreach (CalendarCellElement cell in list)
    {
        if (cell.Date == this.radCalendar1.CalendarElement.View.ViewStartDate)
        {
            if (cell.ControlBoundingRectangle.Y > this.radTextBox1.Location.Y)
            {
                this.radTextBox1.Width = this.radCalendar1.Width - 35;
            }
            else
            {
                this.radTextBox1.Width = cell.ControlBoundingRectangle.X - 20;
            }
        }
 
    }
}

Feel free to modify it so that it fits your scenario. If you face any further difficulties, do not hesitate to contact us.

All the best,
Ivan Todorov
the Telerik team
Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
0
Taylor
Top achievements
Rank 1
answered on 20 Feb 2012, 05:19 PM
That list of elements was a big help.  It still seems odd to me that the list is not solely the cells holding the day entries -- it would be nice if there were a marking interface or something so that I could easily tell what was what.  But, that said, I was able to make it work for my issue.  I'll probably put the code in a separate post, and I'll later mark this as answered.

I still have a problem, though.  It appears, for some reason, that something (I'm guessing the calendar) is preventing my newly embedded RadRichTextBox from receiving enters and spaces. Indeed, calendar itself does not appear to notice those keys; I had assumed it was handling them, so I was going to catch KeyPress/Down and send the necessary info down to the text box, but ... those events don't fire with either the Enter or the SpaceBar.

Is there a way for a RadRichTextBox embedded in a RadCalendar to behave "normally," meaning receiving all the normal events?
0
Taylor
Top achievements
Rank 1
answered on 20 Feb 2012, 05:51 PM
Here is the positioning code. Note that we have a preference of using the bottom row for these purposes.
Private Sub PositionTextbox()
    calMain.Invalidate()
    Dim Elements As List(Of RadElement) = calMain.CalendarElement.GetDescendants(Function(x) TypeOf x Is CalendarCellElement, TreeTraversalMode.BreadthFirst)
    Dim FirstDayCellRectangle As Rectangle = Rectangle.Empty
    Dim LastDayCellRectangle As Rectangle = Rectangle.Empty
    Dim DefaultCellWidth As Integer = -1
    Dim ElementTableRectangle As Rectangle = Rectangle.Empty
    For i As Integer = 0 To Elements.Count - 1
        Dim Cell As CalendarCellElement = Elements(i)
        If i = 0 Then
            ElementTableRectangle = Cell.Parent.ControlBoundingRectangle
            DefaultCellWidth = ElementTableRectangle.Width / 7
        End If
        If Cell.Date = calMain.CalendarElement.View.ViewStartDate Then
            FirstDayCellRectangle = Cell.ControlBoundingRectangle
            'there are multiple of these, but it appears that the last one is the one we want
        ElseIf Cell.Date = calMain.CalendarElement.View.ViewEndDate Then
            LastDayCellRectangle = Cell.ControlBoundingRectangle
            rtbNotes.Height = Cell.ControlBoundingRectangle.Height
            Exit For
        End If
    Next
 
    If FirstDayCellRectangle <> Rectangle.Empty AndAlso LastDayCellRectangle <> Rectangle.Empty AndAlso ElementTableRectangle <> Rectangle.Empty Then
        'a difference of 1 would probably work here, but we use a larger amount in case padding/margins/themes move things
        If LastDayCellRectangle.Bottom < (ElementTableRectangle.Bottom - 20) Then
            'take entire last row
            rtbNotes.Top = ElementTableRectangle.Top + ElementTableRectangle.Height - rtbNotes.Height
            rtbNotes.Width = ElementTableRectangle.Width
            rtbNotes.Left = ElementTableRectangle.Left
        ElseIf LastDayCellRectangle.Left = ElementTableRectangle.Left Then
            'take entire first row
            rtbNotes.Top = FirstDayCellRectangle.Top - FirstDayCellRectangle.Height
            rtbNotes.Width = ElementTableRectangle.Width
            rtbNotes.Left = ElementTableRectangle.Left
        ElseIf (ElementTableRectangle.Width - LastDayCellRectangle.Right) >= FirstDayCellRectangle.Left Then
            'take remainder of last row
            rtbNotes.Top = ElementTableRectangle.Top + ElementTableRectangle.Height - rtbNotes.Height
            rtbNotes.Width = ElementTableRectangle.Width - LastDayCellRectangle.Right
            rtbNotes.Left = ElementTableRectangle.Width - rtbNotes.Width
        Else
            'take remainder of first row
            rtbNotes.Top = FirstDayCellRectangle.Top
            rtbNotes.Width = FirstDayCellRectangle.Left
            rtbNotes.Left = ElementTableRectangle.Left
        End If
    End If
    rtbNotes.BringToFront()
End Sub

0
Accepted
Ivan Todorov
Telerik team
answered on 22 Feb 2012, 10:47 AM
Hi Brandon,

Thank you for posting your code.

As to the issue with the rich text editor inside a calendar, it appears that the calendar steals those input keys from the editor. You can workaround this by creating and using a derived RadCalendar. The following snippet demonstrates how to do this:
Public Class MyCalendar
    Inherits RadCalendar
    Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
        If Not Me.Focused Then
            Return False
        End If
 
        Return MyBase.ProcessCmdKey(msg, keyData)
    End Function
 
    Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
        MyBase.OnMouseDown(e)
        Me.Focus()
    End Sub
 
    Public Overrides Property ThemeClassName() As String
        Get
            Return GetType(RadCalendar).FullName
        End Get
        Set
            MyBase.ThemeClassName = value
        End Set
    End Property
End Class

This is an issue in RadCalendar and therefore I have logged it in our Public Issue Tracking System. You can find the PITS entry by following this link.

Your Telerik points have been updated for bringing this issue to our attention.

Should you have any additional questions, feel free to write back.

Kind regards,
Ivan Todorov
the Telerik team
Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
0
Taylor
Top achievements
Rank 1
answered on 22 Feb 2012, 03:03 PM
That did it.  Thanks!
Tags
Calendar, DateTimePicker, TimePicker and Clock
Asked by
Taylor
Top achievements
Rank 1
Answers by
Ivan Todorov
Telerik team
Taylor
Top achievements
Rank 1
Share this question
or