This question is locked. New answers and comments are not allowed.
Hi Telerik
In my calendar I need to indicate certain days to the user. I don't want to display appointment text but want to display an icon say to indicate birthdays, a different icon to indicate public holidays etc etc.
From what I understand I could do this with special days but i believe that requires a template for each variation.
Is there anyway I can change the background colour of the day or add an icon based on the data for a day? If so, are there any VB examples?
Many thanks
Paul
In my calendar I need to indicate certain days to the user. I don't want to display appointment text but want to display an icon say to indicate birthdays, a different icon to indicate public holidays etc etc.
From what I understand I could do this with special days but i believe that requires a template for each variation.
Is there anyway I can change the background colour of the day or add an icon based on the data for a day? If so, are there any VB examples?
Many thanks
Paul
15 Answers, 1 is accepted
0
Paul
Top achievements
Rank 1
answered on 09 Dec 2011, 12:08 PM
Anyone ?
Pretty please :)
Pretty please :)
0
Chris Pautsch
Top achievements
Rank 1
answered on 13 Dec 2011, 04:33 AM
Yeah, anyone? I'd think there would be a DataBound event or something we can intercept to FindControls and modify them.
0
Hello Paul,
Thank you for your question.
You can use a data template with any content that you want including Images, TextBlocks, etc. for your special days. To define which days should be marked as "special" you should create your own class that inherits DataTemplateSelector and override the SelectTemplate method. There you can define your own custom logic for the dates that use the special template. If need to have more than one template, you will have to define a class for each one of them. An example in C# and in VB about special templates and about other features are available at our online documentation here.
In general, for your special days you just create a DataTemplate and you can place any content inside: Images, TextBlocks, etc. For example, to change the background for a special day to "Red" and add an icon you need a data template like this:
I hope this helps. Do not hesitate to contact us if have any other questions.
Regards,
Todor
the Telerik team
Thank you for your question.
You can use a data template with any content that you want including Images, TextBlocks, etc. for your special days. To define which days should be marked as "special" you should create your own class that inherits DataTemplateSelector and override the SelectTemplate method. There you can define your own custom logic for the dates that use the special template. If need to have more than one template, you will have to define a class for each one of them. An example in C# and in VB about special templates and about other features are available at our online documentation here.
In general, for your special days you just create a DataTemplate and you can place any content inside: Images, TextBlocks, etc. For example, to change the background for a special day to "Red" and add an icon you need a data template like this:
<
DataTemplate
>
<
Grid
Background
=
"Red"
>
<
Image
Source
=
"Images/1.png"
Height
=
"24"
Width
=
"24"
/>
<
TextBlock
Foreground
=
"Black"
Text
=
"{Binding Text}"
/>
</
Grid
>
</
DataTemplate
>
I hope this helps. Do not hesitate to contact us if have any other questions.
Regards,
Todor
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
Chris Pautsch
Top achievements
Rank 1
answered on 13 Dec 2011, 03:39 PM
I completely understand what you're saying and I understand the code in the sample application, but I don't think this will work for me. Please read my scenario below and advise me on how to solve it. Unfortunately, this is very time sensitive and I need to resolve this today. If you cannot reply right away, I completely understand, but I'll then need to use the Resco controls which has an event that allows me to customize the day cell.
In my application, customers can add appointments or tasks. When the calendar is displayed, I need to show up to 4 appts and up to 4 tasks per day. Row 1 is the appts and Row 2 is the tasks. The appts and tasks can also be color coded (e.g. red=urgent). There are 6 colors. So obviously I cannot have a template for each scenario...there would be hundreds of scenarios.
To get it to almost work, I had to put Color:Type in the Subject when loading the control and then use the converter to parse the values. But the problem is that I cannot control which shape is colored and which is not dynamically.
Any ideas? Thanks in advance.
In my application, customers can add appointments or tasks. When the calendar is displayed, I need to show up to 4 appts and up to 4 tasks per day. Row 1 is the appts and Row 2 is the tasks. The appts and tasks can also be color coded (e.g. red=urgent). There are 6 colors. So obviously I cannot have a template for each scenario...there would be hundreds of scenarios.
To get it to almost work, I had to put Color:Type in the Subject when loading the control and then use the converter to parse the values. But the problem is that I cannot control which shape is colored and which is not dynamically.
Any ideas? Thanks in advance.
<DataTemplate x:Key="CustomDayTemplate"> <Grid Margin="5"> <StackPanel Margin="0,-2,0,0"> <Grid Margin="0"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="0" Margin="1" /> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="1" Margin="1" /> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="2" Margin="1" /> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="3" Margin="1" /> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="4" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="0" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="1" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="2" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="3" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="4" Margin="1" /> </Grid> </StackPanel> <TextBlock Text="{Binding Text}" x:Name="TextPresenter" VerticalAlignment="Bottom" HorizontalAlignment="Left"/> </Grid> </DataTemplate>
0
Chris Pautsch
Top achievements
Rank 1
answered on 13 Dec 2011, 03:49 PM
I just had an idea...sort of hacky, but could solve it...unless you have a better idea.
Bind the calendar with appointments where the subject is: Type:Location:Color
For example, A:1:Red = Appt icon #1 color Red, or T:3:Blue = Task icon #3 Blue
When the converter is called for each icon, inspect the DetailText for a match. If one is found, return the color.
Only problem: How do I know which icon is requesting a color?
If I give each shape a name, can I get that from one of the below parameters? I don't think so.
Bind the calendar with appointments where the subject is: Type:Location:Color
For example, A:1:Red = Appt icon #1 color Red, or T:3:Blue = Task icon #3 Blue
When the converter is called for each icon, inspect the DetailText for a match. If one is found, return the color.
Only problem: How do I know which icon is requesting a color?
If I give each shape a name, can I get that from one of the below parameters? I don't think so.
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
0
Chris Pautsch
Top achievements
Rank 1
answered on 13 Dec 2011, 06:32 PM
I kept working at this and almost have the solution...so close. The only issue: When the converter is called, the DetailText keeps stringing together for different dates. When I get the 10 convert calls for the 1st date, I only see the data for that date...good! But when I get the 10 convert calls for the 2nd date, I see the data for the 1st AND 2nd date concatenated. I think you guys have a bug...it doesn't look like you're clearing that property for each date...or is that what you want it to do (I wouldn't think so...I can't see a practical use for that). My "solution" (not coded yet): use a private string variable to save the growing DetailText...when the length changes, "replace" the value passed in so all that;s left is the new date's data...and keep doing that for each call. Ugly, but will work. Thoughts?
XAML:
Load test date:
Converter
XAML:
<DTviews:CalendarBrushConverter x:Key="CalBrushConverter"/> <DataTemplate x:Key="CustomDayTemplate"> <Grid Margin="5"> <StackPanel Margin="0,-2,0,0"> <Grid Margin="0"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="0" Margin="1" /> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="1" Margin="1" /> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="2" Margin="1" /> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="3" Margin="1" /> <Ellipse Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="0" Grid.Column="4" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="0" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="1" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="2" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="3" Margin="1" /> <Rectangle Fill="{Binding Path=DetailText, Converter={StaticResource CalBrushConverter}}" Width="8" Height="8" Grid.Row="1" Grid.Column="4" Margin="1" /> </Grid> </StackPanel> <TextBlock Text="{Binding Text}" x:Name="TextPresenter" VerticalAlignment="Bottom" HorizontalAlignment="Left"/> </Grid> </DataTemplate>
Load test date:
tAppt.Add(new TAppointment() { StartDate = DateTime.Now, EndDate = DateTime.Now, Subject = "12/13/2011~Red~Blue~~~~Green~~~~" }); tAppt.Add(new TAppointment() { StartDate = DateTime.Now, EndDate = DateTime.Now, Subject = "12/14/2011~Green~~~~~Green~Orange~~~" });
Converter
public CalendarBrushConverter() { this.brushes["NONE"] = new SolidColorBrush(Colors.Black); this.brushes["RED"] = new SolidColorBrush(Colors.Red); this.brushes["YELLOW"] = new SolidColorBrush(Colors.Yellow); this.brushes["PURPLE"] = new SolidColorBrush(Colors.Purple); this.brushes["BLUE"] = new SolidColorBrush(Colors.Blue); this.brushes["GREEN"] = new SolidColorBrush(Colors.Green); this.brushes["ORANGE"] = new SolidColorBrush(Colors.Orange); }DateTime lastDate = DateTime.Parse("1/1/1900"); int shapeIndex = 0; public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Brush result = null; //Get the value string color = value as string; //No value? if (color == null || color.Length == 0) color = string.Empty; else { //Remove last line break color = color.Remove(color.Length - 1); //Format: "Date~Color1~Color2~etc." if (color.Contains("~")) { //Get date DateTime currDate = DateTime.Parse(color.Substring(0, color.IndexOf("~"))); //New date? if (currDate != lastDate) { lastDate = currDate; shapeIndex = 0; } else shapeIndex++; //Remove date from string color = color.Substring(color.IndexOf("~") + 1); //Get shape colors from string string[] colors = color.Split("~".ToCharArray()); //Get color from array position color = colors[shapeIndex]; } } //Try to find a match this.brushes.TryGetValue(color.ToUpper(), out result); //No match? Set to foreground color to hide if (result == null) { //result = Application.Current.Resources["PhoneForegroundBrush"] as Brush; this.brushes.TryGetValue("WHITE", out result); } return result; }
0
Chris Pautsch
Top achievements
Rank 1
answered on 13 Dec 2011, 06:49 PM
FYI: It works...but I think you guys still have a bug.
0
Hello Brian,
Now that we have more details on your scenario, the best thing in your case to do is to bind directly to Appointments property (instead to DetailText) in your ItemTemplate.
Then in the converter you can have a direct access to the appointment object (TAppointment). In your TAppointment class you can add any property that will be useful for you to choose the appropriate color.
Please give it a try let us know how it goes.
Greetings, Valentin.Stoychev
the Telerik team
Now that we have more details on your scenario, the best thing in your case to do is to bind directly to Appointments property (instead to DetailText) in your ItemTemplate.
Then in the converter you can have a direct access to the appointment object (TAppointment). In your TAppointment class you can add any property that will be useful for you to choose the appropriate color.
Please give it a try let us know how it goes.
Greetings, Valentin.Stoychev
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
Chris Pautsch
Top achievements
Rank 1
answered on 14 Dec 2011, 04:45 PM
Thanks. That makes sense. I can update that now. But...is there any way to know which shape is calling the Converter? I'm assuming they are called in the sequence they are in the XAML, but that doesn't feel very safe. Can I pass a value in the parameters? Can I give the shapes names and somehow get that in the code behind?
0
Hi Brian Pautsch,
Yes - you can add a parameter to the Binding, which will get passed to the converter. See here more info:
http://www.silverlightshow.net/items/Tip-How-to-pass-a-parameter-to-a-value-converter.aspx
All the best, Valentin.Stoychev
the Telerik team
Yes - you can add a parameter to the Binding, which will get passed to the converter. See here more info:
http://www.silverlightshow.net/items/Tip-How-to-pass-a-parameter-to-a-value-converter.aspx
All the best, Valentin.Stoychev
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
Chris Pautsch
Top achievements
Rank 1
answered on 14 Dec 2011, 10:59 PM
This is excellent guys. Thanks. When I get this done, I'll be sure to post my code to a blog so others can see the full solution.
0
paul
Top achievements
Rank 1
answered on 03 Jan 2012, 08:36 PM
Hi Brian
Did you post your code anywhere?
0
paul
Top achievements
Rank 1
answered on 03 Jan 2012, 08:49 PM
Hi Valentin
"Now that we have more details on your scenario, the best thing in your case to do is to bind directly to Appointments property (instead to DetailText) in your ItemTemplate."
Please could you tell me how I can bind directly to appointments - sorry but I'm a little new to this :)
"Now that we have more details on your scenario, the best thing in your case to do is to bind directly to Appointments property (instead to DetailText) in your ItemTemplate."
Please could you tell me how I can bind directly to appointments - sorry but I'm a little new to this :)
0
Chris Pautsch
Top achievements
Rank 1
answered on 03 Jan 2012, 08:59 PM
Sorry...didn't get around to it yet...here you go:
Note: The code could be further optimized to send in the shape #...but this works well too.
public class CalendarBrushConverter : IValueConverter
{
private Dictionary<string, Brush> brushes = new Dictionary<string, Brush>();
public CalendarBrushConverter()
{
this.brushes["NONE"] = new SolidColorBrush(Colors.Black);
this.brushes["BLACK"] = new SolidColorBrush(Colors.Black);
this.brushes["RED"] = new SolidColorBrush(Colors.Red);
this.brushes["YELLOW"] = new SolidColorBrush(Colors.Yellow);
this.brushes["PURPLE"] = new SolidColorBrush(Colors.Purple);
this.brushes["BLUE"] = new SolidColorBrush(Colors.Blue);
this.brushes["GREEN"] = new SolidColorBrush(Colors.Green);
this.brushes["ORANGE"] = new SolidColorBrush(Colors.Orange);
}
int shapeIndex = -1;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Brush result = null;
//Default
string color = "WHITE";
TAppointment appt = null;
//Anything passed in?
if (value != null)
{
//Attempt to cast the object
LinkedList<IAppointment> apptsTemp = (LinkedList<IAppointment>)value;
//Any appointments in list?
if (apptsTemp.Count > 0)
{
//Get it
appt = (TAppointment)apptsTemp.FirstOrDefault();
//Appt sent in
if (appt != null)
{
//Bump up counter
shapeIndex++;
//Get color from array position
if (appt.ShapeColors[shapeIndex] != null)
color = appt.ShapeColors[shapeIndex];
}
}
}
//Try to find a match
this.brushes.TryGetValue(color.ToUpper(), out result);
//No match? Set to foreground color to hide
if (result == null)
//result = Application.Current.Resources["PhoneForegroundBrush"] as Brush;
this.brushes.TryGetValue("WHITE", out result);
//Clean up
if (shapeIndex == 9)
shapeIndex = -1;
return result;
}
protected virtual object GetValue(string value)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
Note: The code could be further optimized to send in the shape #...but this works well too.
public class CalendarBrushConverter : IValueConverter
{
private Dictionary<string, Brush> brushes = new Dictionary<string, Brush>();
public CalendarBrushConverter()
{
this.brushes["NONE"] = new SolidColorBrush(Colors.Black);
this.brushes["BLACK"] = new SolidColorBrush(Colors.Black);
this.brushes["RED"] = new SolidColorBrush(Colors.Red);
this.brushes["YELLOW"] = new SolidColorBrush(Colors.Yellow);
this.brushes["PURPLE"] = new SolidColorBrush(Colors.Purple);
this.brushes["BLUE"] = new SolidColorBrush(Colors.Blue);
this.brushes["GREEN"] = new SolidColorBrush(Colors.Green);
this.brushes["ORANGE"] = new SolidColorBrush(Colors.Orange);
}
int shapeIndex = -1;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Brush result = null;
//Default
string color = "WHITE";
TAppointment appt = null;
//Anything passed in?
if (value != null)
{
//Attempt to cast the object
LinkedList<IAppointment> apptsTemp = (LinkedList<IAppointment>)value;
//Any appointments in list?
if (apptsTemp.Count > 0)
{
//Get it
appt = (TAppointment)apptsTemp.FirstOrDefault();
//Appt sent in
if (appt != null)
{
//Bump up counter
shapeIndex++;
//Get color from array position
if (appt.ShapeColors[shapeIndex] != null)
color = appt.ShapeColors[shapeIndex];
}
}
}
//Try to find a match
this.brushes.TryGetValue(color.ToUpper(), out result);
//No match? Set to foreground color to hide
if (result == null)
//result = Application.Current.Resources["PhoneForegroundBrush"] as Brush;
this.brushes.TryGetValue("WHITE", out result);
//Clean up
if (shapeIndex == 9)
shapeIndex = -1;
return result;
}
protected virtual object GetValue(string value)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
0
paul
Top achievements
Rank 1
answered on 04 Jan 2012, 02:35 PM
Thank you Brian - just what I needed