As the title says I need to change the calendar's border when it is active (I'm using XamDayView). I can change the CalendarHeader using the IsActive Property but I can't find an easy way to do this for the Border. I want to do something like this:
I'm using a BaseColor for my calendars and a custom color Scheme. Is it better to change the base color or perform the color change at the colorProvider? Or is it simpler to do with triggers or directly in the styles? I'm asking this because I don't feel very comfortable changing Brushes in style when the values are computed...
Thanks for your reply Andrew.
I started doing some work to change that border, so I'll be implementing/testing your sugestion.
Best regards.
The CalendarColorScheme does not have any reference to the elements that are requesting the colors so you wouldn't be able to do this in that class. You may want to submit a suggestion for adding new id's for the Calendar(Border|Header(Background|Foreground)) that relate to when the group contains the ActiveCalendar.
For now you would have to do this in the styles but there are is no property on the CalendarGroupHeaderArea, DayViewDayHeaderArea and CalendarGroupTimeslotArea, which are the 3 elements that comprise what appears as a single group, so you would probably need to create your own multivalueconverter, create styles for those elements based upon copies of the ones we provide in the DefaultStyles but where the BorderBrush used within the template is BorderBrush and not the ComputedBorderBrush. You could then consider the BaseColor of the provider in the converter and calculate the color that you want to use.
So the converter would look something like:
public class ActiveCalendarToBrushConverter : IMultiValueConverter { object IMultiValueConverter.Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (values == null || values.Length != 3) return Binding.DoNothing; var groupCalendar = values[0] as ResourceCalendar; var activeCalendar = values[1] as ResourceCalendar; var brushProvider = values[2] as CalendarBrushProvider; if (groupCalendar == null || activeCalendar == null || brushProvider == null) return Binding.DoNothing; // if its not active then return the default calendar if (groupCalendar != activeCalendar) { return brushProvider.GetBrush(CalendarBrushId.CalendarBorder); } //Color baseColor = brushProvider.BaseColor; //// TODO some calculation of the base color //return new SolidColorBrush(baseColor); return brushProvider.GetBrush(CalendarBrushId.CurrentDayBorder); } object[] IMultiValueConverter.ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { return new object[] { Binding.DoNothing }; } }
var groupCalendar = values[0] as ResourceCalendar; var activeCalendar = values[1] as ResourceCalendar; var brushProvider = values[2] as CalendarBrushProvider;
if (groupCalendar == null || activeCalendar == null || brushProvider == null) return Binding.DoNothing;
// if its not active then return the default calendar if (groupCalendar != activeCalendar) { return brushProvider.GetBrush(CalendarBrushId.CalendarBorder); }
//Color baseColor = brushProvider.BaseColor; //// TODO some calculation of the base color //return new SolidColorBrush(baseColor); return brushProvider.GetBrush(CalendarBrushId.CurrentDayBorder); }
object[] IMultiValueConverter.ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { return new object[] { Binding.DoNothing }; } }
Then you might use it like this:
<local:ActiveCalendarToBrushConverter x:Key="calendarToBrush" /> <Style TargetType="igSchedulePrim:DayViewDayHeaderArea"> <Setter Property="BorderBrush"> <Setter.Value> <MultiBinding Converter="{StaticResource calendarToBrush}"> <!-- DataContext which is the selected calendar of the group --> <Binding /> <!-- ActiveCalendar to compare against --> <Binding RelativeSource="{RelativeSource AncestorType={x:Type ig:ScheduleControlBase}}" Path="ActiveCalendar" /> <!-- The brush provider that is used by the calendar --> <Binding Path="BrushProvider" /> </MultiBinding> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="igSchedulePrim:DayViewDayHeaderArea"> <Border Margin ="{TemplateBinding ComputedMargin}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding ComputedBorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" igPrim:XamlHelper.SnapsToDevicePixels="True"> <Grid igPrim:XamlHelper.SnapsToDevicePixels="{TemplateBinding igPrim:XamlHelper.SnapsToDevicePixels}"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <igSchedulePrim:ScheduleStackPanel x:Name="ItemsPanel" InterItemSpacing="-1"/> <igSchedulePrim:TimeslotPanel x:Name="TimeslotPanel" Grid.Row="1" InterItemSpacing="-1" Visibility="{TemplateBinding MultiDayActivityAreaVisibility}" /> <igSchedulePrim:ScheduleActivityPanel x:Name="ActivityPanel" Grid.Row="1" InterItemSpacing="-1" Visibility="{TemplateBinding MultiDayActivityAreaVisibility}" Margin="1,0"/> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
<!-- ActiveCalendar to compare against --> <Binding RelativeSource="{RelativeSource AncestorType={x:Type ig:ScheduleControlBase}}" Path="ActiveCalendar" />
<!-- The brush provider that is used by the calendar --> <Binding Path="BrushProvider" /> </MultiBinding> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="igSchedulePrim:DayViewDayHeaderArea"> <Border Margin ="{TemplateBinding ComputedMargin}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding ComputedBorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" igPrim:XamlHelper.SnapsToDevicePixels="True"> <Grid igPrim:XamlHelper.SnapsToDevicePixels="{TemplateBinding igPrim:XamlHelper.SnapsToDevicePixels}"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <igSchedulePrim:ScheduleStackPanel x:Name="ItemsPanel" InterItemSpacing="-1"/> <igSchedulePrim:TimeslotPanel x:Name="TimeslotPanel" Grid.Row="1" InterItemSpacing="-1" Visibility="{TemplateBinding MultiDayActivityAreaVisibility}" /> <igSchedulePrim:ScheduleActivityPanel x:Name="ActivityPanel" Grid.Row="1" InterItemSpacing="-1" Visibility="{TemplateBinding MultiDayActivityAreaVisibility}" Margin="1,0"/> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
Here "local:" is just an xmlns mapping to whatever namespace you put that converter (e.g. xmlns:local="clr-namespace:XamScheduleTest"). Note, the only thing changed in the Template from what is in the DefaultStyles is the BorderBrush binding to bind to the BorderBrush property instead of the ComputedBorderBrush property.