2017-02-27 7 views
1

J'ai un contrôle personnalisé, qui ressemble généralement à ceci:WPF contrôle personnalisé à l'intérieur ItemsControl

public class MyTextBlockTest : Control 
{ 
    static MyTextBlockTest() 
    { 
    } 

    public static readonly DependencyProperty TextProperty = 
     DependencyProperty.Register("Text", typeof(string), 
     typeof(MyTextBlockTest), new FrameworkPropertyMetadata("")); 

    public string Text 
    { 
     get { return (string)GetValue(TextProperty); } 
     set { SetValue(TextProperty, value); } 
    } 

    protected override void OnRender(DrawingContext drawingContext) 
    { 
     base.OnRender(drawingContext); 

     FontFamily font = new FontFamily("Times New Roman"); 
     Typeface typeface = new Typeface(font, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); 
     FormattedText ft = new FormattedText(Text, 
              System.Globalization.CultureInfo.CurrentCulture, 
              System.Windows.FlowDirection.LeftToRight, 
              typeface, 
              15.0, 
              Brushes.Black); 

     var point = this.PointToScreen(new Point(0, 0)); 
     drawingContext.DrawText(ft, point);    
    } 
} 

Je suis en train d'utiliser cette commande à l'intérieur d'un ItemsControl:

<ScrollViewer> 
    <ItemsControl ItemsSource="{Binding BigList, ElementName=MainWindowView}" Margin="0,-1,0,1"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <!--<TextBlock Text="{Binding}"/>--> 
       <controls:MyTextBlockTest Text="{Binding}" /> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</ScrollViewer> 

Si activer la TextBlock qui a été commenté, la liste affiche bien; cependant, avec mon contrôle personnalisé, WPF ne place pas le texte au bon endroit; Plus précisément, il semble simplement imprimer tous les éléments les uns sur les autres. L'appel this.PointToScreen était mon idée initiale pour lui donner une invite, mais je ne suis pas sûr (même si cela a fonctionné, ce qui ne fonctionne pas) si cela réagirait favorablement avec le ScrollViewer. Je réalise que je pourrais simplement baser ce contrôle sur le contrôle TextBlock, mais je veux spécifiquement le baser sur un contrôle de niveau inférieur en tant qu'expérience de performance. S'il vous plaît quelqu'un pourrait me diriger vers une méthode pour placer le contrôle personnalisé sur l'écran correctement?

+0

Pourquoi utilisez-vous PointToScreen? Que se passerait-il si seulement dessiner à (0,0)? – Evk

+0

Essayé d'abord, il met juste dans le coin supérieur –

+0

Coin supérieur de contrôle ou ItemsControl? – Evk

Répondre

2

Votre TextBlock minimal personnalisé doit au moins également remplacer la méthode MeasureOverride pour renvoyer sa taille. Sinon, le contrôle a une largeur et une hauteur nulles et tous les éléments de ItemsControl sont dessinés les uns au-dessus des autres. La propriété Text doit donc être enregistrée avec le drapeau FrameworkPropertyMetadataOptions.AffectsMeasure.

public class MyTextBlock : FrameworkElement 
{ 
    private FormattedText formattedText; 

    public static readonly DependencyProperty TextProperty = 
     DependencyProperty.Register(
      "Text", typeof(string), typeof(MyTextBlock), 
      new FrameworkPropertyMetadata(
       string.Empty, 
       FrameworkPropertyMetadataOptions.AffectsMeasure, 
       (o, e) => ((MyTextBlock)o).TextPropertyChanged((string)e.NewValue))); 

    public string Text 
    { 
     get { return (string)GetValue(TextProperty); } 
     set { SetValue(TextProperty, value); } 
    } 

    private void TextPropertyChanged(string text) 
    { 
     var typeface = new Typeface(
      new FontFamily("Times New Roman"), 
      FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); 

     formattedText = new FormattedText(
      text, CultureInfo.CurrentCulture, 
      FlowDirection.LeftToRight, typeface, 15, Brushes.Black); 
    } 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     return formattedText != null 
      ? new Size(formattedText.Width, formattedText.Height) 
      : new Size(); 
    } 

    protected override void OnRender(DrawingContext drawingContext) 
    { 
     if (formattedText != null) 
     { 
      drawingContext.DrawText(formattedText, new Point()); 
     } 
    } 
}