2017-02-27 112 views
1

我有一個自定義的控制,它看起來大致是這樣的:WPF自定義控件內的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);    
    } 
} 

我試圖使用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> 

TextBlock已被註釋掉,列表顯示正常;然而,憑藉我的自定義控件,WPF不會將文本放在正確的位置;更具體地說,它似乎只是將所有元素打印在彼此之上。

this.PointToScreen調用是我最初的想法,它給了它一個提示,但我不確定(即使這工作,它不),這是否會對ScrollViewer產生積極反應。

我意識到我可以簡單地將此控件放置在TextBlock控件上,但我特別想將其作爲性能實驗的底層控件。請有人可以指向我的方法將自定義控件正確顯示在屏幕上?

+0

爲什麼使用PointToScreen? (0,0)時會發生什麼? – Evk

+0

試過最初,它只是把它放在頂角 –

+0

控件或ItemsControl的頂角? – Evk

回答

2

您的最小自定義TextBlock應至少也覆蓋MeasureOverride方法來返回其大小。否則,控件的寬度和高度都爲零,並且ItemsControl中的所有項都被繪製在彼此的頂部。

Text財產因此應註冊與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()); 
     } 
    } 
}