views:

259

answers:

2

Howdy,

My C#/WPF project needs a calendar. We're going to be using it to pick a range of dates for appointment scheduling. I'm told the default calendar is too small to be used by some of our reps so I've been working on resizing it.

<toolkit:Calendar Grid.Row="1" x:Name="DateWindowCalendar" 
   BorderBrush="White" BorderThickness="0"
   Style="{StaticResource PopupCalendarStyle}" 
   DisplayMode="Month" SelectionMode="SingleRange"
   DisplayDateStart="{Binding FirstDayOfMonth}"
   AutomationProperties.AutomationId="ToolkitCalendarId"  
   VerticalAlignment="Top">
 </toolkit:Calendar>

And I've created this styling:

<Style x:Key="PopupCalendarStyle" TargetType="toolkit:Calendar">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="toolkit:Calendar">
        <StackPanel Margin="0" HorizontalAlignment="Center" x:Name="Root">
          <toolkit:Calendar x:Name="Calendar" 
             SelectedDate="{TemplateBinding SelectedDate}"
             DisplayDateStart="{TemplateBinding DisplayDateStart}"
             SelectionMode="{TemplateBinding SelectionMode}"
             Background="{TemplateBinding Background}" 
             BorderBrush="{TemplateBinding BorderBrush}"
             BorderThickness="{TemplateBinding BorderThickness}"
             SelectedDatesChanged="Calendar_SelectedDatesChanged">

             <toolkit:Calendar.CalendarDayButtonStyle>
               <Style>
                 <Setter Property="Button.Height" Value="34"/>
                 <Setter Property="Button.Width" Value="34" />
                 <Setter Property="Button.FontSize" Value="16" />
               </Style>
              </toolkit:Calendar.CalendarDayButtonStyle>

              <toolkit:Calendar.CalendarButtonStyle>
                <Style>
                  <Setter Property="Button.Height" Value="34"/>
                  <Setter Property="Button.Width" Value="34"/>
                  <Setter Property="Button.FontSize" Value="16"/>
                </Style>
              </toolkit:Calendar.CalendarButtonStyle>

            </toolkit:Calendar>
          </StackPanel>
        </ControlTemplate>
      </Setter.Value>
    </Setter>               
  </Style>

Everything is almost perfect. I specify my range, I can track the selected dates (granted using the SelectedDatesChanged event instead of the SelectedDates property.

The problem is I also need to be able to set blackout dates (usually the period between first of the month and today although sometimes first of the month to a few days from now).

Without the styling, this works:

DateWindowCalendar.BlackoutDates.Add(new CalendarDateRange(
   new DateTime(DateTime.Now.Year, DateTime.Now.Month, 01), DateTime.Now));

But when I add the style, I don't get the black out displays being displayed and worse its possible to select the blackout dates.

I'm not sure what I missed but I'm hoping someone has an easy answer so that I don't have to rebuild the entire widget.

Any help is appreciated.

Thanks,

Chris

A: 

In your style I don't see where you are respecting "Blackout dates." What does the base style look like? I assume in the base Style there is an attribute on the Calendar control called blackout dates that is binding to the BlackoutDates Collection.

Something like this :

    <Style x:Key="PopupCalendarStyle" TargetType="toolkit:Calendar">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="toolkit:Calendar">
            <StackPanel Margin="0" HorizontalAlignment="Center" x:Name="Root">
              <toolkit:Calendar x:Name="Calendar" 
                 SelectedDate="{TemplateBinding SelectedDate}"
                 DisplayDateStart="{TemplateBinding DisplayDateStart}"
                 BlackoutDates="{TemplateBinding BlackoutDates}"
                 SelectionMode="{TemplateBinding SelectionMode}"
                 Background="{TemplateBinding Background}" 
                 BorderBrush="{TemplateBinding BorderBrush}"
                 BorderThickness="{TemplateBinding BorderThickness}"
                 SelectedDatesChanged="Calendar_SelectedDatesChanged">

                 <toolkit:Calendar.CalendarDayButtonStyle>
                   <Style>
                     <Setter Property="Button.Height" Value="34"/>
                     <Setter Property="Button.Width" Value="34" />
                     <Setter Property="Button.FontSize" Value="16" />
                   </Style>
                  </toolkit:Calendar.CalendarDayButtonStyle>

                  <toolkit:Calendar.CalendarButtonStyle>
                    <Style>
                      <Setter Property="Button.Height" Value="34"/>
                      <Setter Property="Button.Width" Value="34"/>
                      <Setter Property="Button.FontSize" Value="16"/>
                    </Style>
                  </toolkit:Calendar.CalendarButtonStyle>

                </toolkit:Calendar>
              </StackPanel>
            </ControlTemplate>
          </Setter.Value>
        </Setter>               
      </Style>
Foovanadil
A: 

Okay... that wasn't in it but I'll leave this answer for the next person.

First BlackoutDates is some horrid mish-mash of a readonly collection of ranges. Pretty much unbindable. I poked around with rewriting the widget but didn't get all that far.

I did find something that works. You can set the blackout range in code.

However, if you do this during construction it isn't passed through the template (not sure why). So if you construct a Calendar, and then set the blackout range that works. But when you style that Calendar it doesn't have template bindings (because it isn't a dependency property it can't be bound).

However... it looks like if you set the BlackoutDates through an event generated by the style, then the dates are set. I used the loaded event as so:

            <Style x:Key="PopupCalendarStyle" TargetType="toolkit:Calendar">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="toolkit:Calendar">
                        <StackPanel Margin="0" HorizontalAlignment="Center" x:Name="Root">
                            <toolkit:Calendar x:Name="Calendar" 
                                              SelectedDate="{TemplateBinding SelectedDate}"
                                              DisplayDateStart="{TemplateBinding DisplayDateStart}"
                                              SelectionMode="{TemplateBinding SelectionMode}"
                                              Background="{TemplateBinding Background}" 
                                              BorderBrush="{TemplateBinding BorderBrush}"
                                              BorderThickness="{TemplateBinding BorderThickness}"
                                              SelectedDatesChanged="Calendar_SelectedDatesChanged"
                                              **Loaded="Calendar_Loaded"**>
                                <toolkit:Calendar.CalendarDayButtonStyle>
                                    <Style>
                                        <Setter Property="Button.Height" Value="34"/>
                                        <Setter Property="Button.Width" Value="34" />
                                        <Setter Property="Button.FontSize" Value="16" />
                                    </Style>
                                </toolkit:Calendar.CalendarDayButtonStyle>
                                <toolkit:Calendar.CalendarButtonStyle>
                                    <Style>
                                        <Setter Property="Button.Height" Value="34"/>
                                        <Setter Property="Button.Width" Value="34"/>
                                        <Setter Property="Button.FontSize" Value="16"/>
                                    </Style>
                                </toolkit:Calendar.CalendarButtonStyle>
                            </toolkit:Calendar>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>               
        </Style>

With that done it was fairly trivial to create a load handler that let me set the BlackoutDates on the styled Calendar:

        private void Calendar_Loaded(object sender, RoutedEventArgs e)
    {
        ((Calendar)sender).BlackoutDates.Add(new CalendarDateRange(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 01), DateTime.Now));
    }
Chris