This article is currently in the process of being translated into Portuguese (~99% done).
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 reparou que o controlo Calendar não utiliza todo o espaço vertical disponível. Isto é percetível porque a janela é mais alta do que larga, e por defeito o Viewbox irá esticar enquanto preserva a proporção de aspeto original. Você pode facilmente esticá-lo para preencher todo o espaço em ambas as direções - simplesmente altere a propriedade Stretch do valor por defeito Uniform para 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.
Definindo a vista inicial usando 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);
}
}
}
No Code-behind, simplesmente definimos a propriedade SelectedDate para a data atual mais um dia, ou seja, amanhã. O usuário pode então alterar esta seleção clicando no controle Calendar, e através da vinculação estabelecida na propriedade Text do TextBox, esta alteração será automaticamente refletida ali.
Como bônus adicional, através da magia do vínculo de dados *(data binding)*, você também pode mudar o valor do TextBox - basta inserir uma data válida e a mudança será imediatamente refletida no controle Calendar. Caso você insira uma data inválida, a validação de vínculo automático o notifica do problema:
Trabalhando com múltiplas datas selecionadas
Se você permitir mais de uma data selecionada ao mesmo tempo, não achará a propriedade SelectedDate tão útil. Ao invés disso, você deve usar o SelectedDates, que é uma coleção de datas selecionadas no controle Calendar. Essa propriedade pode ser acessada do Code-behind ou usada com uma vinculação, como fazemos aqui:
<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>
Com uma vinculação simples como essa, nós agora podemos exibir uma lista das datas selecionadas no momento.
Se quiser reagir a datas que estejam a ser alteradas a partir do código, pode subscrever ao evento SelectedDatesChanged do controlo Calendar.
Exclusão de datas (Blackout)
Dependendo para que você usa o controle Calendário, você pode querer ocultar certas datas. Isso pode ser relevante, por exemplo em um aplicativo de reserva, onde você deseja evitar que datas já reservadas sejam selecionadas. O controle Calendar já suporta isso através do uso da coleção BlackoutDates, que você pode usar no XAML e no 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)));
}
}
}
Neste exemplo, demonstro as duas maneiras de adicionar datas ocultas - através do XAML e do Code-behind. Ambas as formas funcionam adicionando instâncias de CalendarDateRange à coleção BlackedoutDates.
Em XAML, estou fixando os intervalos de datas (principalmente para mostrar que também pode ser feito dessa forma), enquanto faço algo um pouco mais inteligente no Code-behind, primeiro adicionando todas as datas anteriores à coleção com uma única chamada ao método AddDatesInPast() e em seguida adicionando um intervalo que consiste em hoje e amanhã.
DisplayMode - mostrando meses ou anos
A propriedade DisplayMode pode alterar o controle do calendário de um lugar onde você pode selecionar uma data para um lugar onde você pode selecionar um mês ou até mesmo um ano. Isso é feito através da propriedade DisplayMode, cujo padrão é Month, que usamos em todos os exemplos anteriores. Aqui está como fica se mudarmos:
<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>
Ao definir o DisplayMode para Year, agora podemos agora selecionar um mês de um determinado ano. Você pode alterar o ano no topo usando as setas.
O controle Calendário também permite selecionar um ano inteiro, usando o valor Decade para a propriedade DisplayMode:
<Calendar DisplayMode="Decade" />
Resumo
Como você pode ver, o controle Calendar é um controle muito versátil com muitas opções e funcionalidades, exigindo apenas um mínimo de configuração para ser usado. Se você estiver construindo um aplicativo com qualquer tipo de funcionalidade relacionada a data, provavelmente será capaz de usar o controle Calendar de uma forma ou de outra.