TextBlock 附加 属性 绑定
TextBlock Attached Property Binding
我正在尝试对我的 Textblockextension
的 属性 进行绑定。我在 CellTemplate
中这样做,但它总是给我一个错误,上面写着:
Binding is not possible for the Property "SetInteractiveText" of type
"TextBlock". Binding can only be done with a DependencyProperty of a
DependencyObject
分机:
public static class TextBlockExtension
{
private static readonly Regex UrlRegex = new Regex(@"(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'"".,<>?«»“”‘’]))", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(500));
private static readonly Regex EmailRegex = new Regex(@"(?("")("".+?(?<!\)""@)|(([0-9a-z]((\.(?!\.))|[-!#$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(500));
private static readonly Regex PhoneRegex = new Regex(@"\+?[\d\-\(\)\. ]{5,}", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
private const string RelativeUriDefaultPrefix = "http://";
public static readonly DependencyProperty InteractiveTextProperty = DependencyProperty.RegisterAttached("InteractiveText", typeof(string), typeof(TextBlock), new UIPropertyMetadata(null,OnInteractiveTextChanged));
private static void OnInteractiveTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBlock = d as TextBlock;
if (textBlock == null) return;
// we remove all the inlines
textBlock.Inlines.Clear();
// if we have no data, we do not need to go further
var rawText = e.NewValue as string;
if (string.IsNullOrEmpty(rawText)) return;
var lastPosition = 0;
var matches = new Match[3];
do
{
matches[0] = UrlRegex.Match(rawText, lastPosition);
matches[1] = EmailRegex.Match(rawText, lastPosition);
matches[2] = PhoneRegex.Match(rawText, lastPosition);
var firstMatch = matches.Where(x => x.Success).OrderBy(x => x.Index).FirstOrDefault();
if (firstMatch == matches[0])
{
// the first match is an URL
CreateRunElement(textBlock, rawText, lastPosition, firstMatch.Index);
lastPosition = CreateUrlElement(textBlock, firstMatch);
}
else if (firstMatch == matches[1])
{
// the first match is an email
CreateRunElement(textBlock, rawText, lastPosition, firstMatch.Index);
}
else if (firstMatch == matches[2])
{
// the first match is a phonenumber
CreateRunElement(textBlock, rawText, lastPosition, firstMatch.Index);
}
else
{
// no match, we add the whole text
textBlock.Inlines.Add(new Run { Text = rawText.Substring(lastPosition) });
lastPosition = rawText.Length;
}
}
while (lastPosition < rawText.Length);
}
private static void CreateRunElement(TextBlock textBlock, string rawText, int startPosition, int endPosition)
{
var fragment = rawText.Substring(startPosition, endPosition - startPosition);
textBlock.Inlines.Add(new Run { Text = fragment });
}
private static int CreateUrlElement(TextBlock textBlock, Match urlMatch)
{
Uri targetUri;
if (Uri.TryCreate(urlMatch.Value, UriKind.RelativeOrAbsolute, out targetUri))
{
var link = new Hyperlink();
link.Inlines.Add(new Run { Text = urlMatch.Value });
if (targetUri.IsAbsoluteUri)
link.NavigateUri = targetUri;
else
link.NavigateUri = new Uri(RelativeUriDefaultPrefix + targetUri.OriginalString);
textBlock.Inlines.Add(link);
}
else
{
textBlock.Inlines.Add(new Run { Text = urlMatch.Value });
}
return urlMatch.Index + urlMatch.Length;
}
public static string GetInteractiveText(DependencyObject obj)
{
return (string)obj.GetValue(InteractiveTextProperty);
}
public static void SetInteractiveText(DependencyObject obj, string value)
{
obj.SetValue(InteractiveTextProperty, value);
}
}
和XAML:
<dxg:TreeListColumn Header="Beschreibung" FieldName="Message" >
<dxg:TreeListColumn.CellTemplate>
<DataTemplate>
<TextBlock utilities:TextBlockExtension.InteractiveText="{Binding Path=(dxg:RowData.Row)}"/>
</DataTemplate>
</dxg:TreeListColumn.CellTemplate>
</dxg:TreeListColumn>
希望有人能帮助我!
附加的属性(即RegisterAttached
的第三个参数)的所有者类型必须是class,其中属性 被声明,而不是应用 属性 的任何可能类型。
这里必须是TextBlockExtension
,不是TextBlock
:
public static readonly DependencyProperty InteractiveTextProperty =
DependencyProperty.RegisterAttached(
"InteractiveText",
typeof(string),
typeof(TextBlockExtension), // here
new PropertyMetadata(null, OnInteractiveTextChanged));
我正在尝试对我的 Textblockextension
的 属性 进行绑定。我在 CellTemplate
中这样做,但它总是给我一个错误,上面写着:
Binding is not possible for the Property "SetInteractiveText" of type "TextBlock". Binding can only be done with a DependencyProperty of a DependencyObject
分机:
public static class TextBlockExtension
{
private static readonly Regex UrlRegex = new Regex(@"(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'"".,<>?«»“”‘’]))", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(500));
private static readonly Regex EmailRegex = new Regex(@"(?("")("".+?(?<!\)""@)|(([0-9a-z]((\.(?!\.))|[-!#$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(500));
private static readonly Regex PhoneRegex = new Regex(@"\+?[\d\-\(\)\. ]{5,}", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
private const string RelativeUriDefaultPrefix = "http://";
public static readonly DependencyProperty InteractiveTextProperty = DependencyProperty.RegisterAttached("InteractiveText", typeof(string), typeof(TextBlock), new UIPropertyMetadata(null,OnInteractiveTextChanged));
private static void OnInteractiveTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBlock = d as TextBlock;
if (textBlock == null) return;
// we remove all the inlines
textBlock.Inlines.Clear();
// if we have no data, we do not need to go further
var rawText = e.NewValue as string;
if (string.IsNullOrEmpty(rawText)) return;
var lastPosition = 0;
var matches = new Match[3];
do
{
matches[0] = UrlRegex.Match(rawText, lastPosition);
matches[1] = EmailRegex.Match(rawText, lastPosition);
matches[2] = PhoneRegex.Match(rawText, lastPosition);
var firstMatch = matches.Where(x => x.Success).OrderBy(x => x.Index).FirstOrDefault();
if (firstMatch == matches[0])
{
// the first match is an URL
CreateRunElement(textBlock, rawText, lastPosition, firstMatch.Index);
lastPosition = CreateUrlElement(textBlock, firstMatch);
}
else if (firstMatch == matches[1])
{
// the first match is an email
CreateRunElement(textBlock, rawText, lastPosition, firstMatch.Index);
}
else if (firstMatch == matches[2])
{
// the first match is a phonenumber
CreateRunElement(textBlock, rawText, lastPosition, firstMatch.Index);
}
else
{
// no match, we add the whole text
textBlock.Inlines.Add(new Run { Text = rawText.Substring(lastPosition) });
lastPosition = rawText.Length;
}
}
while (lastPosition < rawText.Length);
}
private static void CreateRunElement(TextBlock textBlock, string rawText, int startPosition, int endPosition)
{
var fragment = rawText.Substring(startPosition, endPosition - startPosition);
textBlock.Inlines.Add(new Run { Text = fragment });
}
private static int CreateUrlElement(TextBlock textBlock, Match urlMatch)
{
Uri targetUri;
if (Uri.TryCreate(urlMatch.Value, UriKind.RelativeOrAbsolute, out targetUri))
{
var link = new Hyperlink();
link.Inlines.Add(new Run { Text = urlMatch.Value });
if (targetUri.IsAbsoluteUri)
link.NavigateUri = targetUri;
else
link.NavigateUri = new Uri(RelativeUriDefaultPrefix + targetUri.OriginalString);
textBlock.Inlines.Add(link);
}
else
{
textBlock.Inlines.Add(new Run { Text = urlMatch.Value });
}
return urlMatch.Index + urlMatch.Length;
}
public static string GetInteractiveText(DependencyObject obj)
{
return (string)obj.GetValue(InteractiveTextProperty);
}
public static void SetInteractiveText(DependencyObject obj, string value)
{
obj.SetValue(InteractiveTextProperty, value);
}
}
和XAML:
<dxg:TreeListColumn Header="Beschreibung" FieldName="Message" >
<dxg:TreeListColumn.CellTemplate>
<DataTemplate>
<TextBlock utilities:TextBlockExtension.InteractiveText="{Binding Path=(dxg:RowData.Row)}"/>
</DataTemplate>
</dxg:TreeListColumn.CellTemplate>
</dxg:TreeListColumn>
希望有人能帮助我!
附加的属性(即RegisterAttached
的第三个参数)的所有者类型必须是class,其中属性 被声明,而不是应用 属性 的任何可能类型。
这里必须是TextBlockExtension
,不是TextBlock
:
public static readonly DependencyProperty InteractiveTextProperty =
DependencyProperty.RegisterAttached(
"InteractiveText",
typeof(string),
typeof(TextBlockExtension), // here
new PropertyMetadata(null, OnInteractiveTextChanged));