TextBlock附加属性绑定

时间:2017-02-14 09:04:31

标签: c# wpf xaml dependencies attached-properties

我试图对Textblockextension的属性进行绑定。我在CellTemplate中这样做,但它总是给我一个错误,上面写着:

  

Property" SetInteractiveText"无法绑定。类型   " TextBlock的&#34 ;.绑定只能使用a的DependencyProperty来完成   的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>

希望有人可以帮助我!

1 个答案:

答案 0 :(得分:1)

附加属性的所有者类型(即RegisterAttached的第三个参数)必须是声明属性的类,而不是应用属性的任何可能类型。

此处必须是TextBlockExtension,而不是TextBlock

public static readonly DependencyProperty InteractiveTextProperty =
    DependencyProperty.RegisterAttached(
        "InteractiveText",
        typeof(string),
        typeof(TextBlockExtension), // here
        new PropertyMetadata(null, OnInteractiveTextChanged));