我正在尝试创建一个概述文本,我尝试在ShadowEffect
控件上使用Label
,但它没有提供所需的结果而且它非常滞后,唯一的解决方案我到目前为止,我发现可以从Geometry
对象可视化FormattedText
版本。
但是这似乎也有一些问题,即我需要知道控件的宽度和高度,但是例如在带有RowDefinitions的网格中,其大小设置为*
,我似乎找不到获取控件大小的方法,因此我的Geometry没有显示。
这是我的自定义控件类:
public class OutlinedLabel : FrameworkElement
{
private string _text;
public string Text
{
get => _text;
set
{
_text = value;
UpdateLayout();
InvalidateArrange();
InvalidateMeasure();
InvalidateVisual();
}
}
public Brush TextColor
{
get => (Brush)GetValue(TextColorProperty);
set => SetValue(TextColorProperty, value);
}
public static readonly DependencyProperty TextColorProperty =
DependencyProperty.Register(nameof(TextColor), typeof(Brush), typeof(OutlinedLabel),
new PropertyMetadata(null));
public TextAlignment TextAlignment
{
get => (TextAlignment)GetValue(TextAlignmentProperty);
set => SetValue(TextAlignmentProperty, value);
}
public static readonly DependencyProperty TextAlignmentProperty =
DependencyProperty.Register(nameof(TextAlignment), typeof(TextAlignment), typeof(OutlinedLabel),
new PropertyMetadata(null));
public FontWeight FontWeight
{
get => (FontWeight)GetValue(FontWeightProperty);
set => SetValue(FontWeightProperty, value);
}
public static readonly DependencyProperty FontWeightProperty =
DependencyProperty.Register(nameof(FontWeight), typeof(FontWeight), typeof(OutlinedLabel),
new PropertyMetadata(null));
public Brush OutlineBrush
{
get => (Brush)GetValue(OutlineBrushProperty);
set => SetValue(OutlineBrushProperty, value);
}
public static readonly DependencyProperty OutlineBrushProperty =
DependencyProperty.Register(nameof(OutlineBrush), typeof(Brush), typeof(OutlinedLabel),
new PropertyMetadata(null));
public double Thickness
{
get => (double)GetValue(ThicknessProperty);
set => SetValue(ThicknessProperty, value);
}
public static readonly DependencyProperty ThicknessProperty =
DependencyProperty.Register(nameof(Thickness), typeof(double), typeof(OutlinedLabel),
new PropertyMetadata(null));
public FontFamily FontFamily
{
get => (FontFamily)GetValue(FontFamilyProperty);
set => SetValue(FontFamilyProperty, value);
}
public static readonly DependencyProperty FontFamilyProperty =
DependencyProperty.Register(nameof(FontFamily), typeof(FontFamily), typeof(OutlinedLabel),
new PropertyMetadata(null));
public double FontSize
{
get => (double) GetValue(FontSizeProperty);
set => SetValue(FontSizeProperty, value);
}
public static readonly DependencyProperty FontSizeProperty =
DependencyProperty.Register(nameof(FontSize), typeof(double), typeof(OutlinedLabel),
new PropertyMetadata(null));
public OutlinedLabel()
{
FontSize = 12;
Text = string.Empty;
FontFamily = new FontFamily("Seago UI");
TextColor = Brushes.Black;
}
protected override void OnRender(DrawingContext drawingContext)
{
var currentOutlineBrush = OutlineBrush ?? TextColor;
var bg_rect = new Rect(0, 0, ActualWidth, ActualHeight);
drawingContext.DrawRectangle(Brushes.White, null, bg_rect);
var typeface = new Typeface(FontFamily.Source);
var formatted_text = new FormattedText(Text, new CultureInfo("en-us"), FlowDirection, typeface, FontSize,
currentOutlineBrush);
formatted_text.SetFontWeight(FontWeight);
formatted_text.TextAlignment = TextAlignment;
var origin = new Point(ActualWidth / 2, (ActualHeight - formatted_text.Height) / 2);
var geometry = formatted_text.BuildGeometry(origin);
var pen = new Pen(currentOutlineBrush, Thickness);
drawingContext.DrawGeometry(TextColor, pen, geometry);
}
}
这是我的xaml:
<Grid Name="gridSubs" Margin="0,0,0,118" Height="Auto" VerticalAlignment="Stretch" IsHitTestVisible="false">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Viewbox StretchDirection="Both" Stretch="Uniform" Grid.Row="8">
<customControls:OutlinedLabel TextAlignment="Center" TextColor="White" OutlineBrush="Black" FontWeight="Bold" FontSize="32" Thickness="1"/>
</Viewbox>
<Viewbox StretchDirection="Both" Stretch="Uniform" Grid.Row="7">
<customControls:OutlinedLabel TextAlignment="Center" TextColor="White" OutlineBrush="Black" FontWeight="Bold" FontSize="32" Thickness="1"/>
</Viewbox>
//...
</Grid>
当我设置Text
属性时,正在调用OnRender
,但没有任何可见的情况,ActualWidth
和ActualHeight
的值都为0.
如果我创建一个未包含在网格中的OutlinedLabel,该类可以工作。
如何在这种特定情况下使其发挥作用?
答案 0 :(得分:2)
此OutlinedText控件有效。重要的是,它会覆盖MeasureOverride
以确定其ActualWidth
和ActualHeight
。
public class OutlinedText : FrameworkElement
{
private FormattedText text;
public static readonly DependencyProperty TextProperty = TextBlock.TextProperty.AddOwner(
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
public static readonly DependencyProperty TextAlignmentProperty = TextBlock.TextAlignmentProperty.AddOwner(
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsRender = true });
public static readonly DependencyProperty FontSizeProperty = TextBlock.FontSizeProperty.AddOwner(
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
public static readonly DependencyProperty FontFamilyProperty = TextBlock.FontFamilyProperty.AddOwner(
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
public static readonly DependencyProperty FontStyleProperty = TextBlock.FontStyleProperty.AddOwner(
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
public static readonly DependencyProperty FontWeightProperty = TextBlock.FontWeightProperty.AddOwner(
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
public static readonly DependencyProperty FontStretchProperty = TextBlock.FontStretchProperty.AddOwner(
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
public static readonly DependencyProperty ForegroundProperty = TextBlock.ForegroundProperty.AddOwner(
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsRender = true });
public static readonly DependencyProperty BackgroundProperty = TextBlock.BackgroundProperty.AddOwner(
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsRender = true });
public static readonly DependencyProperty OutlineBrushProperty = DependencyProperty.Register(
nameof(OutlineBrush), typeof(Brush), typeof(OutlinedText),
new FrameworkPropertyMetadata(Brushes.White, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((OutlinedText)o).text = null));
public static readonly DependencyProperty OutlineThicknessProperty = DependencyProperty.Register(
nameof(OutlineThickness), typeof(double), typeof(OutlinedText),
new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsMeasure, (o, e) => ((OutlinedText)o).text = null));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public TextAlignment TextAlignment
{
get { return (TextAlignment)GetValue(TextAlignmentProperty); }
set { SetValue(TextAlignmentProperty, value); }
}
[TypeConverter(typeof(FontSizeConverter))]
public double FontSize
{
get { return (double)GetValue(FontSizeProperty); }
set { SetValue(FontSizeProperty, value); }
}
public FontFamily FontFamily
{
get { return (FontFamily)GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
public FontStyle FontStyle
{
get { return (FontStyle)GetValue(FontStyleProperty); }
set { SetValue(FontStyleProperty, value); }
}
public FontWeight FontWeight
{
get { return (FontWeight)GetValue(FontWeightProperty); }
set { SetValue(FontWeightProperty, value); }
}
public FontStretch FontStretch
{
get { return (FontStretch)GetValue(FontStretchProperty); }
set { SetValue(FontStretchProperty, value); }
}
public Brush Foreground
{
get { return (Brush)GetValue(ForegroundProperty); }
set { SetValue(ForegroundProperty, value); }
}
public Brush Background
{
get { return (Brush)GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
public Brush OutlineBrush
{
get { return (Brush)GetValue(OutlineBrushProperty); }
set { SetValue(OutlineBrushProperty, value); }
}
public double OutlineThickness
{
get { return (double)GetValue(OutlineThicknessProperty); }
set { SetValue(OutlineThicknessProperty, value); }
}
protected override Size MeasureOverride(Size availableSize)
{
var size = CheckText() ? new Size(text.Width, text.Height) : new Size();
if (!double.IsNaN(Width) && size.Width < Width)
{
size.Width = Width;
}
if (!double.IsNaN(Height) && size.Height < Height)
{
size.Height = Height;
}
return size;
}
protected override void OnRender(DrawingContext drawingContext)
{
if (CheckText())
{
var size = DesiredSize;
var origin = new Point();
if (size.Width > text.Width)
{
if (TextAlignment == TextAlignment.Center)
{
origin.X = ((size.Width - text.Width) - OutlineThickness) / 2;
}
else if (TextAlignment == TextAlignment.Right)
{
origin.X = (size.Width - text.Width) - OutlineThickness;
}
}
if (size.Height > text.Height)
{
origin.Y = (size.Height - text.Height) / 2;
}
if (Background != null)
{
drawingContext.DrawRectangle(Background, null, new Rect(size));
}
drawingContext.DrawGeometry(Foreground, new Pen(OutlineBrush, OutlineThickness), text.BuildGeometry(origin));
}
}
private bool CheckText()
{
if (text == null)
{
if (string.IsNullOrEmpty(Text))
{
return false;
}
text = new FormattedText(
Text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight,
new Typeface(FontFamily, FontStyle, FontWeight, FontStretch),
FontSize, Brushes.Black);
}
return true;
}
}
答案 1 :(得分:0)
问题是ViewBox
。您的控件需要知道/评估自己的大小才能正确地在ViewBox
内工作。只需删除ViewBox进行测试,您就会看到显示的内容。当您设置Height
的{{1}}和Width
时,文字也会出现。
您可以考虑回复OutlinedLabel
并返回所需的尺寸。
一般来说,我不认为使用ViewBox来克服控件的大小调整问题是最佳做法。控件应该处理所有这些。