Getting visible dates from RadCalendar

6 posts, 2 answers
  1. Taylor
    Taylor avatar
    17 posts
    Member since:
    Oct 2009

    Posted 13 Feb 2012 Link to this post

    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?

  2. Answer
    Ivan Todorov
    Admin
    Ivan Todorov avatar
    688 posts

    Posted 16 Feb 2012 Link to this post

    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 >>
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Taylor
    Taylor avatar
    17 posts
    Member since:
    Oct 2009

    Posted 20 Feb 2012 Link to this post

    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?
  5. Taylor
    Taylor avatar
    17 posts
    Member since:
    Oct 2009

    Posted 20 Feb 2012 Link to this post

    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

  6. Answer
    Ivan Todorov
    Admin
    Ivan Todorov avatar
    688 posts

    Posted 22 Feb 2012 Link to this post

    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 >>
  7. Taylor
    Taylor avatar
    17 posts
    Member since:
    Oct 2009

    Posted 22 Feb 2012 Link to this post

    That did it.  Thanks!
Back to Top
UI for WinForms is Visual Studio 2017 Ready