Найденный Им. Не настолько легкий сделать, по-видимому, существует не создан в Штриховом тексте в WPF (своего рода большая недостающая возможность, если Вы спрашиваете меня). Сначала создайте пользовательский класс:
using System;
using System.Windows.Media;
using System.Globalization;
using System.Windows;
using System.Windows.Markup;
namespace CustomXaml
{
public class OutlinedText : FrameworkElement, IAddChild
{
#region Private Fields
private Geometry _textGeometry;
#endregion
#region Private Methods
/// <summary>
/// Invoked when a dependency property has changed. Generate a new FormattedText object to display.
/// </summary>
/// <param name="d">OutlineText object whose property was updated.</param>
/// <param name="e">Event arguments for the dependency property.</param>
private static void OnOutlineTextInvalidated(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((OutlinedText)d).CreateText();
}
#endregion
#region FrameworkElement Overrides
/// <summary>
/// OnRender override draws the geometry of the text and optional highlight.
/// </summary>
/// <param name="drawingContext">Drawing context of the OutlineText control.</param>
protected override void OnRender(DrawingContext drawingContext)
{
CreateText();
// Draw the outline based on the properties that are set.
drawingContext.DrawGeometry(Fill, new Pen(Stroke, StrokeThickness), _textGeometry);
}
/// <summary>
/// Create the outline geometry based on the formatted text.
/// </summary>
public void CreateText()
{
FontStyle fontStyle = FontStyles.Normal;
FontWeight fontWeight = FontWeights.Medium;
if (Bold == true) fontWeight = FontWeights.Bold;
if (Italic == true) fontStyle = FontStyles.Italic;
// Create the formatted text based on the properties set.
FormattedText formattedText = new FormattedText(
Text,
CultureInfo.GetCultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(Font, fontStyle, fontWeight, FontStretches.Normal),
FontSize,
Brushes.Black // This brush does not matter since we use the geometry of the text.
);
// Build the geometry object that represents the text.
_textGeometry = formattedText.BuildGeometry(new Point(0, 0));
//set the size of the custome control based on the size of the text
this.MinWidth = formattedText.Width;
this.MinHeight = formattedText.Height;
}
#endregion
#region DependencyProperties
/// <summary>
/// Specifies whether the font should display Bold font weight.
/// </summary>
public bool Bold
{
get
{
return (bool)GetValue(BoldProperty);
}
set
{
SetValue(BoldProperty, value);
}
}
/// <summary>
/// Identifies the Bold dependency property.
/// </summary>
public static readonly DependencyProperty BoldProperty = DependencyProperty.Register(
"Bold",
typeof(bool),
typeof(OutlinedText),
new FrameworkPropertyMetadata(
false,
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnOutlineTextInvalidated),
null
)
);
/// <summary>
/// Specifies the brush to use for the fill of the formatted text.
/// </summary>
public Brush Fill
{
get
{
return (Brush)GetValue(FillProperty);
}
set
{
SetValue(FillProperty, value);
}
}
/// <summary>
/// Identifies the Fill dependency property.
/// </summary>
public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
"Fill",
typeof(Brush),
typeof(OutlinedText),
new FrameworkPropertyMetadata(
new SolidColorBrush(Colors.LightSteelBlue),
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnOutlineTextInvalidated),
null
)
);
/// <summary>
/// The font to use for the displayed formatted text.
/// </summary>
public FontFamily Font
{
get
{
return (FontFamily)GetValue(FontProperty);
}
set
{
SetValue(FontProperty, value);
}
}
/// <summary>
/// Identifies the Font dependency property.
/// </summary>
public static readonly DependencyProperty FontProperty = DependencyProperty.Register(
"Font",
typeof(FontFamily),
typeof(OutlinedText),
new FrameworkPropertyMetadata(
new FontFamily("Arial"),
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnOutlineTextInvalidated),
null
)
);
/// <summary>
/// The current font size.
/// </summary>
public double FontSize
{
get
{
return (double)GetValue(FontSizeProperty);
}
set
{
SetValue(FontSizeProperty, value);
}
}
/// <summary>
/// Identifies the FontSize dependency property.
/// </summary>
public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
"FontSize",
typeof(double),
typeof(OutlinedText),
new FrameworkPropertyMetadata(
(double)48.0,
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnOutlineTextInvalidated),
null
)
);
/// <summary>
/// Specifies whether the font should display Italic font style.
/// </summary>
public bool Italic
{
get
{
return (bool)GetValue(ItalicProperty);
}
set
{
SetValue(ItalicProperty, value);
}
}
/// <summary>
/// Identifies the Italic dependency property.
/// </summary>
public static readonly DependencyProperty ItalicProperty = DependencyProperty.Register(
"Italic",
typeof(bool),
typeof(OutlinedText),
new FrameworkPropertyMetadata(
false,
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnOutlineTextInvalidated),
null
)
);
/// <summary>
/// Specifies the brush to use for the stroke and optional hightlight of the formatted text.
/// </summary>
public Brush Stroke
{
get
{
return (Brush)GetValue(StrokeProperty);
}
set
{
SetValue(StrokeProperty, value);
}
}
/// <summary>
/// Identifies the Stroke dependency property.
/// </summary>
public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
"Stroke",
typeof(Brush),
typeof(OutlinedText),
new FrameworkPropertyMetadata(
new SolidColorBrush(Colors.Teal),
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnOutlineTextInvalidated),
null
)
);
/// <summary>
/// The stroke thickness of the font.
/// </summary>
public ushort StrokeThickness
{
get
{
return (ushort)GetValue(StrokeThicknessProperty);
}
set
{
SetValue(StrokeThicknessProperty, value);
}
}
/// <summary>
/// Identifies the StrokeThickness dependency property.
/// </summary>
public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
"StrokeThickness",
typeof(ushort),
typeof(OutlinedText),
new FrameworkPropertyMetadata(
(ushort)0,
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnOutlineTextInvalidated),
null
)
);
/// <summary>
/// Specifies the text string to display.
/// </summary>
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
/// <summary>
/// Identifies the Text dependency property.
/// </summary>
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(OutlinedText),
new FrameworkPropertyMetadata(
"",
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnOutlineTextInvalidated),
null
)
);
public void AddChild(Object value)
{
}
public void AddText(string value)
{
Text = value;
}
#endregion
}
}
Вы могут сослаться на него в Вашем xaml.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:customControls="clr-namespace:CustomXaml;assembly=CustomXaml">
<Grid>
<customControls:OutlinedText x:Name="TextContent" Fill="#ffffffff" FontSize="28"
Bold="True" Stroke="Black" StrokeThickness="1" Text="Back" Margin="10,0,10,0"
HorizontalAlignment="Center" VerticalAlignment="Center" Height="Auto" Width="Auto" />
</Grid>
</Page>
Если сервер поддерживает это, вы должны отправить HTTP-заголовок Range с вашим запросом, используя Метод AddRange :
request.AddRange(1024);
Это заставит сервер начать отправку файла после 1-го килобайта. Затем просто прочитайте поток ответа как обычно.
Чтобы проверить, поддерживает ли сервер возобновление, вы можете отправить запрос HEAD
и проверить, отправляет ли он заголовок Accept-Ranges: bytes
.
Как насчет класса HTTPRangeStream?
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
namespace Ionic.Kewl
{
public class HTTPRangeStream : Stream
{
private string url;
private long length;
private long position;
private long totalBytesRead;
private int totalReads;
public HTTPRangeStream(string URL)
{
url = URL;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
HttpWebResponse result = (HttpWebResponse)request.GetResponse();
length = result.ContentLength;
}
public long TotalBytesRead { get { return totalBytesRead; } }
public long TotalReads { get { return totalReads; } }
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return true; } }
public override bool CanWrite { get { return false; } }
public override long Length { get { return length; } }
public override bool CanTimeout
{
get
{
return base.CanTimeout;
}
}
public override long Position
{
get
{
return position;
}
set
{
if (value < 0) throw new ArgumentException();
position = value;
}
}
public override long Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
position = offset;
break;
case SeekOrigin.Current:
position += offset;
break;
case SeekOrigin.End:
position = Length + offset;
break;
default:
break;
}
return Position;
}
public override int Read(byte[] buffer, int offset, int count)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.AddRange(Convert.ToInt32(position), Convert.ToInt32(position) + count);
HttpWebResponse result = (HttpWebResponse)request.GetResponse();
using (Stream stream = result.GetResponseStream())
{
stream.Read(buffer, offset, count);
stream.Close();
}
totalBytesRead += count;
totalReads++;
Position += count;
return count;
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Flush()
{
throw new NotSupportedException();
}
}
}
Ваше решение в порядке, но оно будет работать только в тех случаях, когда сервер отправляет заголовок Content-Length. Этот заголовок не будет присутствовать в динамически генерируемом контенте.
Кроме того, это решение отправляет запрос для каждого чтения. Если содержимое изменяется на сервере между запросами, вы получите противоречивые результаты.
Я бы улучшил это, сохраняя данные локально - либо на диске, либо в памяти. Тогда вы можете искать в нем все, что хотите. Проблем непоследовательности не возникнет, и для его загрузки потребуется только один HttpWebRequest.