Rozszerzanie kontrolek DataFormXXXField w Telerik RadDataForm

Pracując nad aplikacjami, które korzystają z formularzy Telerika (RadDataForm) często dochodzi do sytuacji, że jakaś kontrolka przeznaczony do umieszczenia na formularzu nie posiada wszystkich własności kontrolki “oryginalnej”, np. RadDatePicker posiada własność InputMode, za pomocą, której możemy ustawić tryb wprowadzania, czyli możemy ustawić wprowadzanie samej daty, godziny lub daty i godziny. Natomiast wersja do użycia w RadDataForm, czyli DataFormDateField nie posiada tej własności i pozwala tylko wyświetlanie i wprowadzanie samej daty.

Przykładowy formularz

Na początku załóżmy, że mamy klasę wizyty oraz formularz edytowania tej wizyty:

Klasa wizyty:

public class Appointment
{
    public Appointment(string customerName, DateTime date)
    {
        this.CustomerName = customerName;
        this.Date = date;
    }
    public string CustomerName { get; set; }
    public DateTime Date { get; set; }
}

Formularz wizyty:

<UserControl x:Class="RadDataFormExtending.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
    xmlns:local="clr-namespace:RadDataFormExtending"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White">
        <telerik:RadDataForm CurrentItem="{Binding Appointment}" AutoEdit="True" AutoGenerateFields="False">
            <telerik:RadDataForm.EditTemplate>
                <DataTemplate>
                    <StackPanel>
                        <telerik:DataFormDataField DataMemberBinding="{Binding CustomerName, Mode=TwoWay}" />
                        <telerik:DataFormDateField DataMemberBinding="{Binding Date, Mode=TwoWay}" />
                    </StackPanel>
                </DataTemplate>
            </telerik:RadDataForm.EditTemplate>
        </telerik:RadDataForm>
    </Grid>
</UserControl>

W kodzie kontrolki zawierającej formularz wizyty tworzymy nową wizytę i wiążemy obiekt kontrolki z DataContext:

public partial class MainPage : UserControl
{
    public MainPage()
    {
        this.DataContext = this;
        this.Appointment = new Appointment("Michał Zalewski", new DateTime(2011, 10, 26, 10, 15, 00));
        InitializeComponent();
    }
    public Appointment Appointment { get; set; }
}

W kodzie formularza specjalnie użyłem własnego EditTemplate, ponieważ będziemy go edytować w następnej części artykułu. Kompilujemy i uruchamiamy aplikację i zamiast daty i godziny w polu Date zobaczymy samą datę. Niestety kontrolka DataFormDateField nie posiada własności InputMode sterującej metodą wprowadzania daty, tak jak to jest w przypadku kontrolki RadDatePicker. Naszym zadaniem jest stworzenie kontrolki, która posiada cechy kontrolki DataFormDateField oraz posiada własność InputMode, która umożliwia ustawienie trybu wprowadzania daty.

Na początek, jak działają kontrolki DataFormXXXField ?

Kontrolki DataFormXXXField działają na zasadzie “opakowania” kontrolki danego typu, czyli np. DataFormDateField opakowuje kontrolkę RadDatePicker. Każda kontrolka tego typu dziedziczy z klasy Telerik.Windows.Controls.DataFormDataField i nadpisuje dwie metody: GetControl() oraz GetControlBindingProperty(). Metoda GetControl() zwraca kontrolkę (np. typu RadDatePicker), która zostanie “opakowana”, natomiast metoda GetControlBindingProperty() zwraca własność “opakowywanej” kontrolki, która zostanie powiązana z własnością DataMemberBinding kontrolki opakowującej, np. dla DataFormDateField będzie to powiązanie z własnością SelectedDate kontrolki typu RadDatePicker.

Jak rozszerzyć kontrolki o nowe własności ?

W celu rozszerzenia kontrolki o dodatkowe własności, np. InputMode w przypadku DataFormDateField, należy stworzyć klasę dziedziczącą z DataFormDateField i dodać do niej własność InputMode, tak jak w przypadku zwykłej kontrolki:

/* usings
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Telerik.Windows.Controls;
*/
public class ExtendedDataFormDateField : DataFormDateField
{
    public static readonly DependencyProperty InputModeProperty =
        DependencyProperty.Register("InputMode", typeof(InputMode), typeof(ExtendedDataFormDateField), new PropertyMetadata(null));
    public InputMode InputMode
    {
        get { return (InputMode)GetValue(InputModeProperty); }
        set { SetValue(InputModeProperty, value); }
    }
}

Następnie musimy zająć się metodą GetControl() i powiązać naszą własność InputMode z własnością InputMode kontrolki opakowanej:

protected override Control GetControl()
{
    RadDatePicker control = (RadDatePicker)base.GetControl();
    control.SetBinding(RadDatePicker.InputModeProperty, new Binding("InputMode") { Source = this });
    return control;
}

Po ustawieniu powiązań i zamianie kontrolki DataFormDateField na naszą ExtendedDataFormDateField w formularzu będziemy mogli się cieszyć nową kontrolką obsługującą różne tryby wprowadzania. Poprawiony szablon edycji w formularzu będzie wyglądał tak:

<telerik:RadDataForm.EditTemplate>
  <DataTemplate>
      <StackPanel>
          <telerik:DataFormDataField DataMemberBinding="{Binding CustomerName, Mode=TwoWay}" />
          <local:ExtendedDataFormDateField InputMode="DateTimePicker" DataMemberBinding="{Binding Date, Mode=TwoWay}" />
      </StackPanel>
  </DataTemplate>
</telerik:RadDataForm.EditTemplate>

Pod spodem znajduje się przykładowy projekt zawierający omówioną kontrolkę oraz formularz.

Przykładowy projekt

2 Comments.

  1. dotnetomaniak.pl - trackback on 24 października 2011 at 15:33

Trackbacks and Pingbacks: