Как добавить события в шаблонное управление в silverlight? - PullRequest
5 голосов
/ 02 декабря 2010

Bounty Вознаграждение за любые солидные учебные / учебные ресурсы по связыванию событий с шаблонными элементами управления.

У меня есть такой шаблон элемента управления:

<Style TargetType="local:DatePicker">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:DatePicker">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}" x:Name="myDatePickerContentArea">
                    <StackPanel Orientation="Vertical">
                        <Button x:Name="myTestButton" Content="Test button"  />
                        <telerik:RadDatePicker Style="{StaticResource VisitsReportTextBoxStyle}" Foreground="#FFFFFF"  x:Name="startDate" DateTimeWatermarkContent="Start Date"/>
                        <telerik:RadDatePicker Style="{StaticResource VisitsReportTextBoxStyle}"  x:Name="endDate" DateTimeWatermarkContent="End Date"/>
                    </StackPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

C # для этого шаблона:

public class DatePicker : Control 
{

    public static readonly DependencyProperty StartDateSelectedDateProperty = DependencyProperty.Register("StartDateSelectedDateProperty", typeof(DateTime), typeof(DatePicker), null);
    public DateTime? StartDateSelectedDate { get; set; }


    public DatePicker()
    {
        this.DefaultStyleKey = typeof(DatePicker);            

    }



    public override void OnApplyTemplate()
    {
        RadDatePicker StartDate = this.GetTemplateChild("startDate") as RadDatePicker;
        StartDate.SelectionChanged += new Telerik.Windows.Controls.SelectionChangedEventHandler(StartDate_SelectionChanged);
        StartDate.SelectedDate = new DateTime(2010, 01, 01);            
        base.OnApplyTemplate();          
    }

    void StartDate_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e)
    {
        RadDatePicker temp = (RadDatePicker)sender;
        StartDateSelectedDate = temp.SelectedDate;
    }


}

Мое событие selectionChanged не срабатывает, и я не знаю почему.Есть идеи?

Ответы [ 2 ]

4 голосов
/ 09 декабря 2010

Вот пример использования передового опыта с тем типом управления, который, я думаю, вы пытаетесь построить (см. Примечания в конце для некоторых объяснений): -

[TemplatePart(Name = DatePicker.ElementStartDate, Type = typeof(RadDatePicker))]
[TemplatePart(Name = DatePicker.ElementEndDate, Type = typeof(RadDatePicker))]
public class DatePicker : Control  
{ 
    public DatePicker() 
    { 
        this.DefaultStyleKey = typeof(DatePicker);             
    } 


    #region Template Part Names
    private const string ElementStartDate = "startDate";
    private const string ElementEndDate = "endDate";
    #endregion

    #region Template Parts
    private RadDatePicker _StartDate;

    internal RadDatePicker StartDate
    {
        get { return _StartDate; }
        private set 
        {
            if (_StartDate != null)
            {
                _StartDate.SelectionChanged -= StartDate_SelectionChanged;
            }

            _StartDate = value;

            if (_StartDate != null)
            {
                _StartDate.SelectionChanged += StartDate_SelectionChanged;
            }
        }
    }

    private RadDatePicker _EndDate;

    internal RadDatePicker EndDate
    {
        get { return _EndDate; }
        private set 
        {
            if (_EndDate!= null)
            {
                _EndDate.SelectionChanged -= EndDate_SelectionChanged;
            }

            _EndDate= value;

            if (_EndDate!= null)
            {
                _EndDate.SelectionChanged += EndDate_SelectionChanged;
            }
        }
    }

    #endregion

    public static readonly DependencyProperty StartDateSelectedDateProperty =
        DependencyProperty.Register(
            "StartDateSelectedDateProperty",
             typeof(DateTime?),
             typeof(DatePicker),
             new PropertyMetaData(new DateTime(2010, 01, 01)));

    public DateTime? StartDateSelectedDate
    {
        get { return (DateTime?)GetValue(StartDateSelectedDateProperty); }
        set { SetValue(StartDateSelectedDateProperty)} 
    }

    public static readonly DependencyProperty EndDateSelectedDateProperty =
        DependencyProperty.Register(
            "EndDateSelectedDateProperty",
             typeof(DateTime?),
             typeof(DatePicker),
             new PropertyMetaData(new DateTime(2010, 01, 01)));

    public DateTime? EndDateSelectedDate 
    {
        get { return (DateTime?)GetValue(EndDateSelectedDateProperty); }
        set { SetValue(EndDateSelectedDateProperty)} 
    }

    public override void OnApplyTemplate() 
    { 
        base.OnApplyTemplate();           

        StartDate = GetTemplateChild(ElementStartDate) as RadDatePicker; 
        EndDate =  GetTemplateChild(ElementEndDate) as RadDatePicker; 
    } 

    void StartDate_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e) 
    { 
        // Do stuff with StartDate here
    } 

    void EndDate_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e) 
    { 
        // Do stuff with EndDate here
    }     
} 

Шаблон Xaml должен выглядеть следующим образом:-

<Style TargetType="local:DatePicker">                                 
    <Setter Property="Template">                                 
        <Setter.Value>                                 
            <ControlTemplate TargetType="local:DatePicker">                                 
                <Border Background="{TemplateBinding Background}"                                 
                        BorderBrush="{TemplateBinding BorderBrush}"                                 
                        BorderThickness="{TemplateBinding BorderThickness}" x:Name="myDatePickerContentArea">                                 
                    <StackPanel Orientation="Vertical">                                 
                        <Button x:Name="myTestButton" Content="Test button"  />                                 
                        <telerik:RadDatePicker x:Name="startDate"
                            Style="{StaticResource VisitsReportTextBoxStyle}"
                            Foreground="#FFFFFF"
                            DateTimeWatermarkContent="Start Date"
                            SelectedDate="{TemplateBinding StartDateSelectedDate}"
                         />                                 
                        <telerik:RadDatePicker x:Name="endDate"
                            Style="{StaticResource VisitsReportTextBoxStyle}"
                            DateTimeWatermarkContent="End Date"
                            SelectedDate="{TemplateBinding EndDateSelectedDate}"
                        />                                 
                    </StackPanel>                                 
                </Border>                                 
            </ControlTemplate>                                 
        </Setter.Value>                                 
    </Setter>                                 
</Style>

Некоторые пояснения

  • Ключевая проблема вашего исходного кода заключалась в том, что он неправильно реализовал свойства зависимостей.Обратите внимание, что в свойствах теперь используются GetValue и SetValue, а также что метаданные свойства используются для назначения значения по умолчанию, а не для попытки установки в onapplytemplate.
  • При правильно реализованных свойствах привязка шаблона должна работатьи на самом деле мы закончили с получением того, что кажется вашим первоначальным намерением, поэтому я упустил любой фактический код в обработчиках событий.
  • Создание констант в коде для хранения имен ключейчасти шаблона, с которыми вы хотите взаимодействовать, это позволяет сделать изменения имен менее дорогостоящими.
  • Добавьте TemplatePart атрибутов к классу, чтобы указать ключевые элементы, которые код ожидает найти, каковы их именадолжно быть и какой базовый тип они должны иметь.Это позволяет дизайнеру повторно шаблонировать существующий элемент управления, пока присутствуют объявленные части шаблона, когда элемент управления должен работать правильно, даже если его пользовательский интерфейс радикально изменен.
  • Если вам необходимо подключить обработчики событий для некоторыхэлементы создают поле для хранения ссылки на элемент, а затем создают свойство для его обтекания.Затем установщик свойства должен отсоединить и прикрепить обработчики событий, как вы видите в коде.
  • Убедитесь, что bae.OnApplyTemplate вызывается в переопределении OnApplyTemplate, так как вы можете видеть его довольно простым для назначения созданного выше.properties.
  • У меня нет RadDatePicker, поэтому я не могу проверить, единственное, что меня беспокоит, это то, где DateTime? - правильный тип для свойства SelectedDate.Конечно, если это улучшение по сравнению с предложением Microsoft, которое, похоже, не соответствует этому типичному требованию ввода данных.
3 голосов
/ 02 декабря 2010

Я могу только догадываться, что проблема в том, что для метода OnApplyTemplate Разработчики должны всегда вызывать базовую реализацию перед своей собственной реализацией.
Другое дело, что из вашего кода лучше выглядитиспользуйте TemplateBinding ( Archive ) ( V4 ) в шаблоне xaml

<telerik:RadDatePicker SelectedDate={TemplateBinding StartDateSelectedDate}
                       Style="{StaticResource VisitsReportTextBoxStyle}" 
                       Foreground="#FFFFFF"  x:Name="startDate" 
                       DateTimeWatermarkContent="Start Date"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...