2017-02-14 8 views
2

私はTextblockextensionのプロパティでバインドしようとしています。私はCellTemplateであることをやっているが、それは常に言う1つのエラーことを私に与えます:TextBlock添付プロパティバインディング

バインディングは、タイプ 「のTextBlock」のプロパティ「SetInteractiveText」ことは不可能です。

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> 

誰かが私を助けることを願って結合が唯一 のDependencyObject

拡張のたDependencyPropertyで行うことができます!

+0

これは、バインディングは、タイプ "のTextBlock" のプロパティ "SetInteractiveText" ことは不可能であると言います。バインドはDependencyObjectのDependencyPropertyでのみ行うことができます – Sokui

+0

'AttachedProperty'のデスティネーションターゲットタイプを' TextBlockExtension'に変更します。最初:今は 'TextBlock'のタイプですが、' TextBlock'はそのようなプロパティを持っていません!! this - > 'typeof(TextBlock)'を 'typeof(TextBlockExtension)'に変更してください。 – Shakra

+0

@Shakraありがとう!それはそれを修正! – Sokui

答えて

1

添付プロパティ(RegisterAttachedの第3引数)のオーナータイプは、プロパティが適用されるクラスでなく、プロパティが宣言されたクラスでなければなりません。

ここではTextBlockExtension、ないTextBlockでなければなりません:

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