2017-02-27 2 views
1

ich eine benutzerdefinierte Kontrolle haben, die im Großen und Ganzen wie folgt aussieht:WPF Custom Control innerhalb Items

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

Ich versuche, diese Kontrolle innerhalb eines ItemsControl zu verwenden:

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

Wenn ich die Freigabe TextBlock das ist auskommentiert, die Liste zeigt gut an; Mit meinem benutzerdefinierten Steuerelement platziert WPF den Text jedoch nicht an der richtigen Stelle. genauer gesagt, es scheint einfach alle Elemente übereinander zu drucken.

Der this.PointToScreen Aufruf war meine anfängliche Idee, es eine Eingabeaufforderung zu geben, aber ich bin unsicher (auch wenn das funktionierte, was es nicht tut), ob dies mit dem ScrollViewer positiv reagieren würde.

Ich weiß, ich könnte dieses Steuerelement einfach auf das TextBlock-Steuerelement basieren, aber ich möchte es speziell als Performance-Experiment von einer niedrigeren Ebene Steuerelement basieren. Könnte mich jemand auf eine Methode hinweisen, mit der das benutzerdefinierte Steuerelement korrekt auf dem Bildschirm angezeigt wird?

+0

Warum verwenden Sie PointToScreen? Was würde passieren, wenn man nur (0,0) zeichnet? – Evk

+0

Versucht, dass es zunächst nur in der oberen Ecke –

+0

oberen Ecke der Steuerung oder ItemsControl? – Evk

Antwort

2

Ihr minimaler benutzerdefinierter TextBlock sollte mindestens die Methode MeasureOverride überschreiben, um seine Größe zurückzugeben. Andernfalls hat das Steuerelement die Breite und Höhe null, und alle Elemente im ItemsControl werden übereinander gezeichnet.

Die Eigenschaft sollte daher mit dem FrameworkPropertyMetadataOptions.AffectsMeasure Flag registriert werden.

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