TOC

This article is currently in the process of being translated into Portuguese (~58% done).

Controles diversos:

The Calendar control

O WPF vem com um controle para exibir um calendário completo, pronto para usar. É tão simples que você só precisa colocá-lo dentro de sua janela para ter a vista de um calendário completo, como este:

<Window x:Class="WpfTutorialSamples.Misc_controls.CalendarControlSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CalendarControlSample" Height="250" Width="300">
    <Grid>
<Calendar />
    </Grid>
</Window>

Repare como você obteve uma lista inteira com as datas do mês selecionado, incluindo a possibilidade de saltar entre meses através das setas para a direita e para a esquerda no topo do controlo. Caso você selecione não uma data específica, o mês atual será mostrado assim como a data atual será marcada por predefinição.

Tamanho do Calendário

Você deve ter reparado que no primeiro exemplo o calendário não ocupa todo o espaço disponível. De facto, mesmo que você aumente a sua altura e largura, o próprio calendário apenas ocupará o espaço que está demonstrado na foto, e se você definir os valores muito pequenos, o calendário apenas estará parcialmente visível.

O comportamento do tamanho fixo não é muito típico do WPF, onde os controles esticam-se para preencher todo o espaço disponível, o que pode ser um pouco frustrante se você tiver designado um certo espaço para o calendário preencher. No entanto, para nós, no WPF tudo é dimensionável, mas no caso do controle do Calendário, ele precisa de um pouco de ajuda. Portanto para este propósito vamos usar o controle ViewBox:

<Window x:Class="WpfTutorialSamples.Misc_controls.CalendarViewboxSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CalendarViewboxSample" Height="350" Width="300">
    <Viewbox>
<Calendar />
    </Viewbox>
</Window>

Repare em como o Calendário se ajusta até ao ponto onde usa todo o espaço disponível na sua largura. O dimensionamento é feito em todas as partes do controle, incluíndo tamanho da fonte e da grossura das bordas.

Você provavelmente também notará que o controle do Calendário não consome todo o espaço de altura disponível. Isto é perceptível porque a janela é mais alta do que é larga e, por padrão, a Viewbox irá esticar mantendo a relação de aspecto original. Você pode facilmente fazê-lo esticar para preencher todo o espaço em ambas as direções - simplesmente mude a propriedade Stretch do valor padrãoUniform para o valor Fill:

<Window x:Class="WpfTutorialSamples.Misc_controls.CalendarViewboxSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CalendarViewboxSample" Height="350" Width="300">
    <Viewbox Stretch="Fill" StretchDirection="UpOnly">
<Calendar />
    </Viewbox>
</Window>

Agora ocupa todo o espaço disponível, em ambas as direções. Isto geralmente não é preferível, já que a maioria dos controles, e este em particular, vai parecer estranho se ele receber um conjunto anormal de dimensões, por exemplo, 800 pixels de altura e 300 pixels de largura. O modo Stretch definido como Uniform (ou deixado de fora, pois é o padrão) é geralmente o caminho a seguir.

Eu recomendaria incluir a propriedade StretchDirection, no entanto, como visto neste exemplo. Ele nos permite especificar que o conteúdo só deve ser escalado para cima ou para baixo, o que pode ser útil. Por exemplo, o controle do Calendário torna-se bastante inútil abaixo de um certo tamanho, onde você não pode mais ver o que ele é, e para evitar isso, você pode definir a propriedade StretchDirection para UpOnly - o controle do Calendário não será mais escalado abaixo do seu tamanho padrão.

Setting the initial view using DisplayDate

O controle do Calendário irá por padrão mostrar o mês atual, mas você pode alterar isso usando a propriedade DisplayDate. Basta configurá-la para uma data dentro do mês que você deseja começar e ela será refletida no controle:

<Window x:Class="WpfTutorialSamples.Misc_controls.CalendarDisplayDateSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CalendarDisplayDateSample" Height="300" Width="300">
    <Viewbox>
<Calendar DisplayDate="01.01.2014" />
    </Viewbox>
</Window>

Modo de Seleção de Calendário

A propriedade SelectionMode é interessante. Alterando-a do seu valor padrão, SingleDate, você pode selecionar várias datas ou intervalos de datas. Aqui está um exemplo:

<Window x:Class="WpfTutorialSamples.Misc_controls.CalendarSelectionModeSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CalendarSelectionModeSample" Height="300" Width="300">
    <Viewbox>
<Calendar SelectionMode="SingleRange" />
    </Viewbox>
</Window>

No SingleRange SelectionMode, você pode selecionar toda uma série de datas, seja segurando o botão esquerdo do mouse e arrastando de uma data para outra ou segurando as teclas Ctrl ou Shift enquanto clica em várias datas, assim como a seleção múltipla funciona em todas as partes do Windows. Na captura de tela, eu selecionei uma semana inteira, de domingo a segunda-feira, mas você também pode selecionar datas facilmente no meio da semana e intervalos que expandem uma única semana.

O modo SingleRange permite apenas a seleção de um único intervalo de datas, como o nome sugere. Isto significa que você não pode selecionar duas datas que não estejam próximas uma da outra, e não pode selecionar mais de um intervalo de datas. Se você quiser isso, você deve mudar a seleção para MultipleRange:

<Calendar SelectionMode="MultipleRange" />

Com esta propriedade, realmente não há limites para as datas que você pode selecionar. Neste caso, selecionei todos os sábados, todos os domingos e alguns dias no meio da semana.

Naturalmente, se você não quiser a capacidade de selecionar uma ou várias datas, você pode definir o SelectionMode para None.

Agora vamos discutir como podemos trabalhar com a(s) data(s) selecionada(s) do controle do Calendário.

Trabalhando com a data selecionada

A propriedade SelectedDate é tudo o que você precisa se você só permitir seleções únicas (veja a explicação acima sobre modos de seleção). Ela permite que você defina e obtenha uma data selecionada no momento, a partir do Code-behind, bem como através de uma ligação de dados.

Aqui está um exemplo onde definimos a data selecionada para amanhã a partir do Code-behind e depois usamos uma ligação de dados para ler a data selecionada para um controle TextBox:

<Window x:Class="WpfTutorialSamples.Misc_controls.CalendarSelectionSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CalendarSelectionSample" Height="280" Width="220">
    <StackPanel Margin="10">
<Calendar Name="cldSample" SelectionMode="MultipleRange" SelectedDate="10.10.2013" />
<Label>Selected date:</Label>
<TextBox Text="{Binding ElementName=cldSample, Path=SelectedDate, StringFormat=d, UpdateSourceTrigger=PropertyChanged}" />
    </StackPanel>
</Window>
using System;
using System.Windows;

namespace WpfTutorialSamples.Misc_controls
{
    public partial class CalendarSelectionSample : Window
    {
public CalendarSelectionSample()
{
    InitializeComponent();
    cldSample.SelectedDate = DateTime.Now.AddDays(1);
}
    }
}

In Code-behind, we simply set the SelectedDate property to the current date plus one day, meaning tomorrow. The user can then change this selection by clicking in the Calendar control, and through the data binding established in Text property of the TextBox, this change will automatically be reflected there.

As an added bonus, through the magic of data binding, you can also change the value from the TextBox - just input a valid date and the change will be immediately reflected in the Calendar control. Should you enter a bad date, the automatic binding validation notifies you of the problem:

Working with multiple selected dates

If you allow more than one selected date at the time, you won't find the SelectedDate property that useful. Instead, you should use the SelectedDates, which is a collection of currently selected dates in the Calendar control. This property can be accessed from Code-behind or used with a binding, like we do here:

<Window x:Class="WpfTutorialSamples.Misc_controls.CalendarSelectedDatesSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CalendarSelectedDatesSample" Height="420" Width="220">
    <StackPanel Margin="10">
<Calendar Name="cldSample" SelectionMode="MultipleRange" />
<Label>Selected dates:</Label>
<ListBox ItemsSource="{Binding ElementName=cldSample, Path=SelectedDates}" MinHeight="150" />
    </StackPanel>
</Window>

With a simple binding like that, we're now able to display a list of the currently selected dates.

If you want to react to dates being changed from Code-behind, you can subscribe to the SelectedDatesChanged event of the Calendar control.

Blackout dates

Depending on what you use the Calendar control for, you may want to black out certain dates. This could be relevant e.g. in a booking application, where you want to prevent already reserved dates from being selected. The Calendar control supports this right out of the box through the use of the BlackoutDates collection, which you can of course use from both XAML and Code-behind:

<Window x:Class="WpfTutorialSamples.Misc_controls.CalendarBlockedoutDatesSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CalendarBlockedoutDatesSample" Height="300" Width="300">
    <Viewbox>
<Calendar Name="cldSample" SelectionMode="MultipleRange">
    <Calendar.BlackoutDates>
<CalendarDateRange Start="10.13.2013" End="10.19.2013" />
<CalendarDateRange Start="10.27.2013" End="10.31.2013" />
    </Calendar.BlackoutDates>
</Calendar>
    </Viewbox>
</Window>
using System;
using System.Windows;
using System.Windows.Controls;

namespace WpfTutorialSamples.Misc_controls
{
    public partial class CalendarBlockedoutDatesSample : Window
    {
public CalendarBlockedoutDatesSample()
{
    InitializeComponent();
    cldSample.BlackoutDates.AddDatesInPast();
    cldSample.BlackoutDates.Add(new CalendarDateRange(DateTime.Today, DateTime.Today.AddDays(1)));
}
    }
}

In this example, I demonstrate both ways of adding blacked out dates - through XAML and through Code-behind. Both ways works by adding instances of CalendarDateRange to the BlackedoutDates collection.

In XAML, I'm hardcoding the date ranges (mostly to show you it can be done that way too), while I do something a bit more clever in Code-behind, by first adding all past dates to the collection with a single call to the AddDatesInPast() method and then adding a range consisting of today and tomorrow.

DisplayMode - showing months or years

The DisplayMode property can change the Calendar control from a place where you can select a date to a place where you can select a month or even a year. This is done through the DisplayMode property, which defaults to Month, which we've used in all the previous examples. Here's how it looks if we change it:

<Window x:Class="WpfTutorialSamples.Misc_controls.CalendarDisplayModeSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CalendarDisplayModeSample" Height="300" Width="300">
    <Viewbox>
<Calendar DisplayMode="Year" />
    </Viewbox>
</Window>

By setting the DisplayMode to Year, we can now select a month of a given year. You can change the year in the top, by using the arrows.

The Calendar control also allows for selecting an entire year, by using the Decade value for the DisplayMode property:

<Calendar DisplayMode="Decade" />

Summary

As you can see, the Calendar control is a very versatile control with lots of options and functionality, requiring only a minimum of configuration to use. If you're building an application with any sort of date-related functionality, you will probably be able to use the Calendar control, one way or another.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!