【问题标题】:How to add events to templated control in silverlight?如何在 Silverlight 中向模板化控件添加事件?
【发布时间】:2010-12-01 22:59:27
【问题描述】:

任何有关使用模板化控件连接事件的可靠教程/学习资源都会获得赏金奖励。

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

<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 事件没有触发,我不知道为什么。 有什么想法吗?

【问题讨论】:

  • 如果有人知道任何关于带有事件示例的模板化控件的教程或文章,将不胜感激。
  • 好吧,至少我不是一个人在搜索自定义控件的信息。

标签: silverlight silverlight-4.0


【解决方案1】:

这是一个使用最佳实践和我认为您正在尝试构建的控件的示例(请参阅末尾的注释以获取一些解释):-

[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 产品的改进,Microsoft 产品似乎已经放弃了这种典型的数据输入要求。

【讨论】:

    【解决方案2】:

    我可能只猜测问题出在 OnApplyTemplate 方法Implementers should always call the base implementation before their own implementation.
    另一件事是,从您的代码看来,最好在模板 xaml 中使用 TemplateBinding(Archive)(V4)

    <telerik:RadDatePicker SelectedDate={TemplateBinding StartDateSelectedDate}
                           Style="{StaticResource VisitsReportTextBoxStyle}" 
                           Foreground="#FFFFFF"  x:Name="startDate" 
                           DateTimeWatermarkContent="Start Date"/>
    

    【讨论】:

    • 这些都没有任何效果。虽然 =D
    猜你喜欢
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多