如何在Silverlight中向模板控件添加事件?

5

有关使用模板控件连接事件的任何实用教程/学习资源,将奖励赏金。

我有一个这样的控件模板:

<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事件不会触发,我不确定原因。有什么想法吗?


1
如果有人知道任何关于带有事件示例的模板控件的教程或文章,那将不胜感激。 - BentOnCoding
1
至少我在寻找自定义控件的信息方面不孤单。 - BentOnCoding
2个回答

4

以下是使用最佳实践的示例,该控件与您尝试构建的控件类似(有关一些解释,请参见末尾的注释):

[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>

一些解释

  • 您原始代码的一个关键问题是未正确实现依赖属性。请注意,属性现在使用GetValueSetValue,并且属性元数据用于分配默认值,而不是尝试在onapplytemplate中设置。
  • 如果正确实现了属性,则模板绑定应该可以工作,实际上,我们已经完成了看起来是您最初意图的所有内容,因此我在事件处理程序中略去了任何实际代码。
  • 在代码中创建常量以保存要与之交互的关键模板部件的名称,这样可以更少地更改名称。
  • 向类添加TemplatePart属性,以指示代码希望找到的关键元素,它们的名称应该是什么以及它们预期具有的基本类型。这允许设计师重新为现有控件制定模板,只要声明的模板部件存在于控件的某个地方,控件就应该能够正确地运行,即使其UI发生了根本性的改变。
  • 如果需要为某些元素附加事件处理程序,请创建一个字段以保存对该元素的引用,然后创建一个属性以包装该元素。属性设置器应该像代码中所示那样分离和附加事件处理程序。
  • 确保在OnApplyTemplate的覆盖中调用bae.OnApplyTemplate,然后您可以看到分配上面创建的属性非常简单。
  • 我没有RadDatePicker,因此无法进行测试,我唯一尚未解决的问题是DateTime?是否为SelectedDate属性的正确类型。如果是这样,它是对Microsoft提供的改进,似乎它已经放弃了这个典型的数据输入要求。

3

这两者都没有任何影响。 谢谢你 =D - BentOnCoding

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接