2010-12-01 15 views
5

Recompensa Bounty por cualquier tutorial sólido/recursos de aprendizaje relacionados con el cableado de eventos con controles de plantilla.¿Cómo agregar eventos al control de plantilla en Silverlight?

Tengo una plantilla de control de esta manera:

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

El C# para esta plantilla es:

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; 
    } 


} 

Mi SelectionChanged No desencadena el evento y no estoy seguro de por qué. ¿Alguna idea?

+1

Si alguien conoce algún tutorial o artículo sobre controles con plantillas con ejemplos de eventos que realmente se agradecerán. – BentOnCoding

+1

Bueno, al menos no estoy solo en mi búsqueda de información sobre controles personalizados. – BentOnCoding

Respuesta

4

Aquí se muestra un ejemplo de la utilización de las mejores prácticas con el tipo de control que creo que está tratando de construir (ver las notas al final para algunas explicaciones): -

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

La plantilla Xaml debe verse como: -

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

Algunas explicaciones

  • Un problema clave de su código original tenía era que no había aplicado las propiedades de dependencia correctamente. Tenga en cuenta que las propiedades ahora usan GetValue y SetValue, también que los metadatos de propiedad se utilizan para asignar el valor predeterminado en lugar de intentar establecerlo en onapplytemplate.
  • Con las propiedades implementadas correctamente, el enlace de la plantilla debería funcionar y, de hecho, hemos terminado hasta obtener lo que parece ser su intención original, por lo tanto, he omitido cualquier código real en los controladores de eventos.
  • Cree constantes en el código para contener los nombres de las partes clave de la plantilla con las que desea interactuar, esto permite que los cambios de nombre sean menos costosos de realizar.
  • Agregue TemplatePart atributos a la clase para indicar los elementos clave que el código espera encontrar, cuáles deberían ser sus nombres y qué tipo base se espera que tengan. Esto permite que un diseñador vuelva a crear una plantilla de un control existente, siempre que las partes de la plantilla declaradas estén presentes mientras el control funcione correctamente, incluso si su interfaz de usuario se altera radicalmente.
  • Si necesita adjuntar manejadores de eventos para algunos elementos, cree un campo para mantener una referencia al elemento y luego cree una propiedad para envolverlo. El organizador de propiedades debe separar y adjuntar los controladores de eventos como se ve en el código.
  • Asegúrese de llamar a bae.OnApplyTemplate en la sustitución de OnApplyTemplate, ya que puede ver que es muy sencillo asignar las propiedades creadas anteriormente.
  • No tengo RadDatePicker, así que no puedo probar, mi única preocupación es dónde el DateTime? es el tipo correcto para la propiedad SelectedDate. Sin duda, si se trata de una mejora con respecto a la oferta de Microsoft, que parece haber perdido el control en este requisito típico de entrada de datos.
3

que sólo puede adivinar que el problema es que para el método OnApplyTemplate Implementers should always call the base implementation before their own implementation.
La otra cosa es que a partir de su código parece que es mejor usar TemplateBinding (Archive) (V4) en el xaml plantilla

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

Ninguno de estos tuvo ningún efecto. Thnxs though = D – BentOnCoding

Cuestiones relacionadas