2010-12-01 5 views
5

Bounty Récompense pour tout tutoriel solide/ressources d'apprentissage concernant le câblage des événements avec des contrôles basés sur des modèles.Comment ajouter des événements à un contrôle basé sur un modèle dans Silverlight?

J'ai un modèle de contrôle comme celui-ci:

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

Le C# pour ce modèle est:

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


} 

Mon selectionChanged événement ne se déclenche pas et je ne sais pas pourquoi. Des idées?

+1

Si quelqu'un connaît des didacticiels ou des articles sur les contrôles basés sur des modèles avec des exemples d'événements qui seraient vraiment appréciés. – BentOnCoding

+1

Eh bien au moins je ne suis pas seul dans ma recherche d'informations sur les contrôles personnalisés. – BentOnCoding

Répondre

4

Voici un exemple d'utilisation de bonnes pratiques avec le genre de contrôle, je pense que vous essayez de construire (voir les notes à la fin des explications): -

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

Le modèle Xaml devrait ressembler à: -

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

Quelques explications

  • Un problème clé de votre code d'origine a été qu'il n'a pas mis en œuvre les propriétés de dépendance correctement. Notez que les propriétés utilisent maintenant GetValue et SetValue, également que les métadonnées de propriété sont utilisées pour affecter la valeur par défaut plutôt que d'essayer de définir dans onapplytemplate. Avec les propriétés correctement implémentées, la liaison de modèle devrait fonctionner et, en fait, nous avons fini d'obtenir ce qui semble être votre intention d'origine, par conséquent j'ai omis tout code réel dans les gestionnaires d'événements.
  • Créez des constantes dans le code pour stocker les noms des parties de modèle de clé avec lesquelles vous souhaitez interagir, ce qui permet d'effectuer des modifications de nom moins coûteuses.
  • Ajoutez TemplatePart attributs à la classe pour indiquer les éléments clés que le code s'attend à trouver, leur nom et le type de base attendu. Cela permet à un concepteur de réajuster un contrôle existant, tant que les parties de modèle déclarées sont présentes quelque part le contrôle devrait fonctionner correctement même si son interface utilisateur est radicalement modifiée.
  • Si vous devez attacher des gestionnaires d'événements pour certains éléments, créez un champ pour contenir une référence à l'élément, puis créez une propriété pour l'entourer. Le setter de propriété doit ensuite détacher et attacher les gestionnaires d'événements comme vous le voyez dans le code.
  • Assurez-vous que bae.OnApplyTemplate est appelé dans le remplacement de OnApplyTemplate, car vous pouvez le voir assez simple pour affecter les propriétés créées ci-dessus.
  • Je n'ai pas le RadDatePicker donc je ne peux pas tester, ma seule préoccupation en suspens est où le DateTime? est le type correct pour la propriété SelectedDate. Certainement si c'est une amélioration par rapport à l'offre de Microsoft qui semble avoir laissé tomber la balle sur cette exigence de saisie de données typique.
3

je peux seulement deviner que le problème est que pour la méthode OnApplyTemplate Implementers should always call the base implementation before their own implementation.
L'autre chose est que de votre code, il ressemble il est préférable d'utiliser TemplateBinding (Archive) (V4) dans le modèle XAML

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

Ni l'un ni l'autre n'a eu d'effet. Thnxs si = D – BentOnCoding

Questions connexes