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

Row selection only

22 Answers 204 Views
Calendar, DateTimePicker, TimePicker and Clock
This is a migrated thread and some comments may be shown as answers.
Lovsten
Top achievements
Rank 1
Lovsten asked on 01 Oct 2007, 11:19 AM
It there a way to deactivate the selection of dates from the individule days on the calendar?  This way the only way anyone could select anything it would be on a week-by-week basis (via the row (week) number).  Then be able to pull the dates that were selected from that row?

22 Answers, 1 is accepted

Sort by
0
Boyko Markov
Telerik team
answered on 02 Oct 2007, 09:23 AM
Thank you for the question, Lovsten.

We currently do not have a built-in way to disable selection of the individual cells, but  you can use the following workaround:
  1. Subscribe to the SelectionChanging event of RadCalendar
  2. Write the following in the event handler: 
     
        foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)     
                {     
                    if ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty))     
                    {     
                        e.Cancel = false;     
                    }     
                    else    
                    {     
                        e.Cancel = true;     
                    }     
                }    
     

This code block is iterating through the cells of the RadTableElement - the element which layouts and renders the calendar cells. The code checks if the cell is a header cell or a content cell: if the cell is a content cell, then it will not be selected, but if you click with the mouse on a particular cell, or move around the content area using the keyboard arrows then the focused cell will be changed. 

I hope this helps. If you need some more assistance please write back. 


Regards,
Boyko Markov
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 02 Oct 2007, 10:24 AM
Thanks Boyko. That worked.

But I only want the user to select one and only one week. 
Right now the user can select many weeks.

I got AllowMultipleSelect = True. Thats right, aint it? Since we selecting a full row. Tried to do .selectedDates.clear in the event you suggested, but that doesn't do anything.

I also want to preselect a certain week with code before showing the calendar. How do I do that?
0
Boyko Markov
Telerik team
answered on 02 Oct 2007, 03:43 PM
Hi Magnus,

Here is a solution for having only one selected week at a time:

Create a few variables to hold the values of the selected header row and column:

private int headerCellRow = -1;  
private int headerCellColumn = -1;  
private int oldHeaderCellRow = -1;  
private int oldHeaderCellColumn = -1;  

 

Create a boolean instance that will give us information whether the selection is changing. For the sake of this example, I have named it changingSelection.

private bool changingSelection;  
 
 
 

Initialize the following properties of RadCalendar:

 this.radCalendar1.AllowColumnHeaderSelectors = true;  
 this.radCalendar1.ShowColumnHeaders = true;  
 this.radCalendar1.AllowMultipleSelect = true;  
     

Subscribe to the following events:

this.radCalendar1.MouseDown += new MouseEventHandler(radCalendar1_MouseDown);  
this.radCalendar1.SelectionChanging += new Telerik.WinControls.UI.SelectionEventHandler(radCalendar1_SelectionChanging);  
this.radCalendar1.SelectionChanged += new EventHandler(radCalendar1_SelectionChanged);  
         

If you look at the following code snippet you will notice that I have modified the code in the event handler of the SelectionChanging event so it will comply to the new behavior.
 

    void radCalendar1_SelectionChanging(object sender, Telerik.WinControls.UI.SelectionEventArgs e)  
        {  
            if (!this.changingSelection)  
            {  
                foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
                {  
                    if ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty))  
                    {  
                        if (cell.RectangleToScreen(cell.Bounds).Contains(Cursor.Position))  
                        {  
                            this.oldHeaderCellRow = headerCellRow;  
                            this.oldHeaderCellColumn = headerCellColumn;  
 
                            this.headerCellRow = cell.Row;  
                            this.headerCellColumn = cell.Column;  
                        }  
                    }  
                }  
            }  
        } 

What I do next is to iterate through the calendar cells and verify whether the cell is part of the header cells. If it is a header cell I'm initializing the oldHeaderCellRow, headerCellRow, oldHeaderCellColumn and headerCellColumn fields to  prepare them for later usage. In the event handler of the SelectionChanged event is the logic which unselects a cell if it is part of the content cells.
 

    foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
            {  
                if (cell.RectangleToScreen(cell.Bounds).Contains(Cursor.Position))  
                {  
                    if (false == ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty)))  
                    {  
                        this.radCalendar1.SelectedDates.Remove(cell.Date);  
                    }  
                }  
            }  
 
            this.radCalendar1.InvalidateCalendar(); 

Maybe the most important part is the code inside the mouse down event handler. It is unselecting the last selected row/column.
 

void radCalendar1_MouseDown(object sender, MouseEventArgs e)  
        {  
            bool shouldProceed = false;  
 
            foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
            {  
                if (cell.RectangleToScreen(cell.Bounds).Contains(Cursor.Position))  
                {  
                    if (true == ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty)))  
                    {  
                        shouldProceed = true;  
                    }  
                }  
            }  
 
            if (shouldProceed)  
            {  
                this.changingSelection = true;  
 
                foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
                {  
                    if (false == ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty)))  
                    {  
                        if (this.oldHeaderCellRow == 0)  
                        {  
                            if (cell.Column == this.oldHeaderCellColumn)  
                            {  
                                this.radCalendar1.SelectedDates.Remove(cell.Date);  
                                 
                            }  
                        }  
                        else 
                            if (this.oldHeaderCellColumn == 0)  
                            {  
                                if (cell.Row == this.oldHeaderCellRow)  
                                {  
                                    this.radCalendar1.SelectedDates.Remove(cell.Date);  
                                }  
                            }  
                    }     
                }  
            }  
            this.changingSelection = false;  
        } 


You may ask why do I need to use a field like changingSelection? Well, I use fields like oldHeaderCellRow here which I initialize in the SelectionChanging event Handler but when I call the Remove method of a DateTimeCollection I'm changing the collection, so the fields which I will be re-initialized with wrong values. The very simple solution which popped up to me was to set the changingSelection field to true when I'm starting to modify the collection so when the SelectionChanging event is fired nothing will happen. After I've modified the dateTimeCollection I'm setting the changingSelection field back to false.

I hope this helps.



Regards,

Boyko Markov

the Telerik team


Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 03 Oct 2007, 10:23 AM
I use VB so I converted the code in your code converter.
However problem with 2 properties in your code:
                            this.headerCellRow = cell.Row;  
                            this.headerCellColumn = cell.Column;  

cell.Row and cell.Column gives error
Error 6 'column' is ambiguous because multiple kinds of members with this name exist in class 'Telerik.WinControls.UI.CalendarCellElement' 
Error 6 'row' is ambiguous because multiple kinds of members with this name exist in class 'Telerik.WinControls.UI.CalendarCellElement'

Same problem in mousedown event.

Running Q2 2007.
0
Lovsten
Top achievements
Rank 1
answered on 03 Oct 2007, 10:28 AM
Also want to preselect a certain week with code before showing the calendar. How do I do that? Don't think that was in the code?
0
Boyko Markov
Telerik team
answered on 03 Oct 2007, 12:45 PM
Hello Lovsten,

I could suggest the following method to select an entire week:

    public void SelectAWeek(DateTime dateTime)  
        {  
            for (int i = 0; i < 7; i++)  
            {  
                this.radCalendar1.SelectedDates.Add(this.radCalendar1.DefaultView.CurrentCalendar.AddDays(dateTime, i+1));  
            }  
        } 

This method functions in the following fashion. It adds a sequence of seven dates to the SelectedDates collection, after the one you've passed as an argument. The Column and Row are fields of CalendarCellElement. We've marked them public, but for the service pack which is scheduled for the next week they will be set back to internal as they are only for internal usage. 

The column and row properties will be renamed to Column and Row as the fields at the moment. Please try to use the column and row properties instead of the Row and Column fields.

If you need additional assistance we will be happy to help you.

Regards,
Boyko Markov
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 03 Oct 2007, 02:29 PM
The selectAWeek worked perfect. Thanks.

But still problem with row and Column. These are not listed as proerties or fields in VB. Intellisense does not show them at all.
0
Boyko Markov
Telerik team
answered on 04 Oct 2007, 04:28 PM
Yep, these are new properties, which will be part of SP1, but are not yet available to the public. I did not  notice this when I wrote my reply.

In this case, I could suggest the following solution:

  • Define a new class extending the CalendarCellElement
internal class CalendarCellElementExtended : CalendarCellElement  
    {  
        private int row;  
        private int column;  
        private CalendarCellElement cell;  
 
        public CalendarCellElementExtended(RadCalendar calendar, CalendarView view)  
            : base(calendar, view)  
        {  
        }  
          
        public int Row  
        {  
            get 
            {  
                return this.row;  
            }  
            internal set 
            {  
                this.row = value;  
            }  
        }  
 
        public CalendarCellElement Cell  
        {  
            get 
            {  
                return this.cell;  
            }  
            internal set 
            {  
                this.cell = value;  
            }  
        }  
 
 
        public int Column  
        {  
            get 
            {  
                return this.column;  
            }  
            internal set 
            {  
                this.column = value;  
            }  
        }  
    } 


  • Create the following list holding the instances of our new class 

    private List<CalendarCellElementExtended> cellElements = new List<CalendarCellElementExtended();

  • Create the following method and call it for example in the constructor after the initialization of your componentsÖ

    private void InitializeCells()  
            {  
                this.cellElements.Clear();            
                int currentRow = 0;  
                int currentColumn = 0;  
                int rows = this.radCalendar1.Rows;  
                int columns = this.radCalendar1.Columns;  
              
                if (this.radCalendar1.ShowViewSelector)  
                {  
                    columns += 1;  
                    rows += 1;  
                }  
                else 
                {  
                    if (this.radCalendar1.ShowRowHeaders)  
                    {  
                        rows += 1;  
                    }  
     
                    if (this.radCalendar1.ShowColumnHeaders)  
                    {  
                        columns += 1;  
                    }  
                }  
                  
                foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
                {  
                    CalendarCellElementExtended extendedCell = new CalendarCellElementExtended(this.radCalendar1, this.radCalendar1.DefaultView);  
                    extendedCell.Row = currentRow;  
                    extendedCell.Column = currentColumn;  
                    extendedCell.Cell = cell;  
     
                    currentColumn++;  
                    if (currentColumn == columns)  
                    {  
                        currentColumn = 0;  
                        currentRow++;  
                    }  
     
                    this.cellElements.Add(extendedCell);  
                }  
            } 

    This method iterates through the cells of the calendar instance and then creates an instance of the extended cell and initializes it by setting its Cell, Row and Column properties.

  • The last step which we have to do is to modify a bit the code which we have used before in the mouse down handler and in the selection changing event handler:

    void radCalendar1_MouseDown(object sender, MouseEventArgs e)  
            {  
                bool shouldProceed = false;  
     
                foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
                {  
                    if (cell.RectangleToScreen(cell.Bounds).Contains(Cursor.Position))  
                    {  
                        if (true == ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty)))  
                        {  
                            shouldProceed = true;  
                        }  
                    }  
                }  
     
                if (shouldProceed)  
                {  
                    this.changingSelection = true;  
     
                    foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
                    {  
                        CalendarCellElementExtended extendedCell = GetAssociatedCell(cell);  
     
                        if (false == ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty)))  
                        {  
                            if (this.oldHeaderCellRow == 0)  
                            {  
                                if (extendedCell.Column == this.oldHeaderCellColumn)  
                                {  
                                    this.radCalendar1.SelectedDates.Remove(cell.Date);  
                                }  
                            }  
                            else 
                                if (this.oldHeaderCellColumn == 0)  
                                {  
                                    if (extendedCell.Row == this.oldHeaderCellRow)  
                                    {  
                                        this.radCalendar1.SelectedDates.Remove(cell.Date);  
                                    }  
                                }  
                        }     
                    }  
                }  
                this.changingSelection = false;  
            } 

     

        void radCalendar1_SelectionChanging(object sender, Telerik.WinControls.UI.SelectionEventArgs e)  
            {  
                if (!this.changingSelection)  
                {  
                    foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
                    {  
                        if ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty))  
                        {  
                            if (cell.RectangleToScreen(cell.Bounds).Contains(Cursor.Position))  
                            {  
                                this.oldHeaderCellRow = headerCellRow;  
                                this.oldHeaderCellColumn = headerCellColumn;  
     
                                CalendarCellElementExtended extendedCell = GetAssociatedCell(cell);  
     
                                this.headerCellRow = extendedCell.Row;  
                                this.headerCellColumn = extendedCell.Column;  
                            }  
                        }  
                    }  
                }  
            } 

    The only difference here is that I use the Row and Column properties of the new defined class extending the regular CalendarCellElement. I have added a new method which I have named GetAssociatedCell, the purpose of which is to return an instance of the extended cell based on the cell which you pass as an argument. Its code you can find it the next snippet:

    private CalendarCellElementExtended GetAssociatedCell(CalendarCellElement cell)  
            {  
                foreach (CalendarCellElementExtended extendedCell in cellElements)  
                {  
                    if (extendedCell.Cell.Equals(cell))  
                    {  
                        return extendedCell;  
                    }  
                }  
     
                return null;  
     
            } 

     

I hope that this will help.

 
Kind regards,

Boyko Markov

the Telerik team


Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 10 Oct 2007, 07:23 AM
Hi. When will the SP1 released? This week I've heard. Is there a date set? We are going live next week and would like to get this functionality in.
0
Vassil Petev
Telerik team
answered on 10 Oct 2007, 02:51 PM
Hi Lovsten,

The Service Pack should be live tomorrow. We are in the final QA phase, and I am sure that we will be able to upload the new version tomorrow.


Regards,

Vassil Petev
Product Manager
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 12 Oct 2007, 05:33 AM
Still no SP?
0
Kiril
Telerik team
answered on 12 Oct 2007, 08:58 AM
Hi Lovsten,

The RadControls for Winforms Q2 Service Pack 1 is available on our website.

Please uninstall the old version of RadControls for Winforms before installing the new one to make sure your projects reference the newest version of our product.

All the best,
Kiril
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 12 Oct 2007, 12:21 PM
I now have SP1 and implemented to code you wrote here. Does not work very well.

Issue 1: If I select first week in a month and the change to next month and select first week, then both gets selected.

Issue 2: If use your SelectAWeek function when loading it then this week always is selected.

Issue 3: If use select a week and the whole get selected. Then user can click on a date in that week and it gets unselect. Best would be that a click on a date would select the entire week. If not possible, then at least that click should not be allowed.


Hoping for a quick solution, since we are going live middle of next week
0
Boyko Markov
Telerik team
answered on 12 Oct 2007, 02:59 PM
Hello Lovsten,

If you would like to clear the selection of a cell you should use one of the methods in the SelectedDates collection of RadCalendar, for example Remove, RemoveRange and Clear.

More information about the RadCalendar you can find in the documentation.

I hope this helps.

Regards,
Boyko Markov
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 13 Oct 2007, 12:53 PM
Hi. That was not very much help considering your sample code had that many errors. I was expecting new sample code that would correct your initial code from obvious errors.
0
Boyko Markov
Telerik team
answered on 15 Oct 2007, 12:30 PM
Hello Lovsten,

The logic I've provided you in the sample source code is to demonstrate how easy you can modify the built-in selection logic of RadCalendar. We don't have a built-in behavior for the custom behavior you are expecting by the control.

However, here is an updated code snippet with the modifications which you've requested.

The solution is to modify the source in the mouse down handler using the following code:

void radCalendar1_MouseDown(object sender, MouseEventArgs e)     
        {     
            bool shouldProceed = false;  
 
            this.invertSelection = false;  
 
            foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
            {  
                if (cell.RectangleToScreen(cell.Bounds).Contains(Cursor.Position))  
                {  
                  
                        if (true == ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty)))  
                        {  
                            shouldProceed = true;  
                        }  
                        else 
                        {  
                            if (this.radCalendar1.SelectedDates.Contains(cell.Date))  
                                this.invertSelection = true;  
                        }  
                }  
            }  
 
            if (shouldProceed)  
            {  
                this.radCalendar1.SelectedDates.Clear();  
            }  
              
        } 


As you see in the code snippet I invoke the Clear method of the SelectedDates collection of RadCalendar. This modification is needed when you select a week and then move to a new month and select a new week. The SelectedDates collection is a container of the selected dates in RadCalendar. So when you need to remove any date from its selection state you should call one of the methods of this collection like the ones I've suggested you in the last post. 

Declare a new boolean field named: invertSelection and modify the code in the SelectionChanged handler in the following way:

void radCalendar1_SelectionChanged(object sender, EventArgs e)  
        {  
              
            foreach (CalendarCellElement cell in ((CalendarTableElement)((MonthViewElement)((RadCalendarElement)this.radCalendar1.RootElement.Children[0]).CalendarVisualElement).Children[0].Children[1]).Children)  
            {  
                if (cell.RectangleToScreen(cell.Bounds).Contains(Cursor.Position))  
                {  
                    if (false == ((bool)cell.GetValue(CalendarCellElement.IsHeaderCellProperty)))  
                    {  
                        if (!this.invertSelection)  
                            this.radCalendar1.SelectedDates.Remove(cell.Date);  
                        else 
                            this.radCalendar1.SelectedDates.Add(cell.Date);  
                    }  
                }  
            }  
 
            this.radCalendar1.InvalidateCalendar();   
        } 

Remove the code from the SelectionChanging handler. Please write me back if this need more modifications and I'm going to update the code block.  

I'm looking forward to your response.

Best wishes,
Boyko Markov
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 15 Oct 2007, 01:06 PM
That worked better. Only one little problem left. Today's date is always selected when if I use you SelectAWeek. I tried to do cal.SelectedDates.clear in it and still the same. How can I get ride off it?
0
Boyko Markov
Telerik team
answered on 15 Oct 2007, 01:44 PM
Hello Lovsten,

Are you sure that the Today's date is always selected when you use the SelectAWeek method?

We have a special visual state for the Today's date and it resembles the look of the selected date. However, in this particular case today's date is not logically selected.

Could you please send us screenshots showing the behavior without calling the SelectAWeek method and the behavior when the method is called?

Greetings,
Boyko Markov
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 15 Oct 2007, 02:03 PM
Can't add pictures here.

 With code below calPromotionFrom selects today and next week (15 oct, 22-28 oct). calPromotionTo (with commented out code) has nothing selected.

                        SelectAWeek(calPromotionFrom, Now.Date.AddDays(7))  
                        calPromotionFrom.FocusedDate = Now.Date.AddDays(7)  
'                        SelectAWeek(calPromotionTo, Now.Date.AddMonths(1).AddDays(-1))  
'                        calPromotionTo.FocusedDate = Now.Date.AddMonths(1).AddDays(-1)  
 
I've modified to SelectAWeek to always select Mon-Sun. This is MyCode

 

Public Sub SelectAWeek(ByRef cal As RadCalendar, ByVal dateTime As DateTime)  
 
Dim i As Integer = 0  
 
While dateTime.DayOfWeek <> DayOfWeek.Monday  
 
dateTime = dateTime.AddDays(-1)  
 
End While 
 
While i < 7  
 
cal.SelectedDates.Add(cal.DefaultView.CurrentCalendar.AddDays(dateTime, i))  
 
i += 1  
 
End While 
 
End Sub 
 

 

0
Boyko Markov
Telerik team
answered on 15 Oct 2007, 03:02 PM
Hello Lovsten,

I suggest subtracting the time value when you pass a dateTime parameter to the SelectAWeek method.
Use the following pattern: 

this.SelectAWeek(DateTime.Now.Subtract(DateTime.Now.TimeOfDay));

I'm not completely sure how you'd like us to improve this method. Could you please give me more specific information about the desired behavior? To send screenshots or sample projects you should open a new support ticket and then attach the images/projects you would like to send us.

We're looking forward to your reply.

Kind regards,
Boyko Markov
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Lovsten
Top achievements
Rank 1
answered on 16 Oct 2007, 05:40 AM
DateTime.Now.Subtract(DateTime.Now.TimeOfDay) is the exact same thing as DateTime.Now.Date.

Started new support ticket. Hoping for a quick solution to this.
0
Boyko Markov
Telerik team
answered on 16 Oct 2007, 08:26 AM
Hi Lovsten,

I agree with you on the last suggestion. I've sent you a solution via a support ticket.

Thank you for writing.

Greetings,
Boyko Markov
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
Tags
Calendar, DateTimePicker, TimePicker and Clock
Asked by
Lovsten
Top achievements
Rank 1
Answers by
Boyko Markov
Telerik team
Lovsten
Top achievements
Rank 1
Vassil Petev
Telerik team
Kiril
Telerik team
Share this question
or