public static void SetSource(DependencyObject element, HyperlinkTextProperties value)
        {
            if (element == null)
            {
                return;
            }

            element.SetValue(SourceProperty, value);
        }
        private static void Replace(TextBlock textBlock, HyperlinkTextProperties links)
        {
            int hashtagSuffix = 0;
            int mentionSuffix = 0;
            int urlSuffix     = 0;

            if (links.Hashtags == null)
            {
                links.Hashtags = new List <HashtagEntity>();
            }

            if (links.Mentions == null)
            {
                links.Mentions = new List <UserMentionEntity>();
            }

            if (links.Urls == null)
            {
                links.Urls = new List <UrlEntity>();
            }

            int index;
            int treatedIndex          = -1;
            var untreatedHashtagExist = hashtagSuffix < links.Hashtags.Count;
            var untreatedMentionExist = mentionSuffix < links.Mentions.Count;
            var untreatedUrlExist     = urlSuffix < links.Urls.Count;

            while (true)
            {
                index = 99999;

                if (untreatedHashtagExist)
                {
                    index = Math.Min(index, links.Hashtags[hashtagSuffix].Indices[0]);
                }

                if (untreatedMentionExist)
                {
                    index = Math.Min(index, links.Mentions[mentionSuffix].Indices[0]);
                }

                if (untreatedUrlExist)
                {
                    index = Math.Min(index, links.Urls[urlSuffix].Indices[0]);
                }

                if (index == 99999)
                {
                    break;
                }

                // サロゲートペアを2文字とした場合のindexの数値を計算
                int surrogateIndex = CalculateSurrogateIndex(links.Text, index);

                // 置換するリンクまでをプレーンテキストとして流し込む
                textBlock.Inlines.Add(new Run()
                {
                    Text = Escape(links.Text.Substring(treatedIndex + 1, surrogateIndex - treatedIndex - 1), links.Media)
                });
                treatedIndex = surrogateIndex;

                // ハッシュタグの置換
                if (untreatedHashtagExist && index == links.Hashtags[hashtagSuffix].Indices[0])
                {
                    ReplaceHashtag(textBlock, links.Hashtags[hashtagSuffix], links.HashtagCommand);
                    treatedIndex += links.Hashtags[hashtagSuffix].Indices[1] - links.Hashtags[hashtagSuffix].Indices[0] - 1;
                    hashtagSuffix++;
                }
                // メンションの置換
                else if (untreatedMentionExist && index == links.Mentions[mentionSuffix].Indices[0])
                {
                    ReplaceMention(textBlock, links.Mentions[mentionSuffix], links.MentionCommand);
                    treatedIndex += links.Mentions[mentionSuffix].Indices[1] - links.Mentions[mentionSuffix].Indices[0] - 1;
                    mentionSuffix++;
                }
                // URLの置換
                else if (untreatedUrlExist && index == links.Urls[urlSuffix].Indices[0])
                {
                    ReplaceUrl(textBlock, links.Urls[urlSuffix], links.UrlCommand);
                    treatedIndex += links.Urls[urlSuffix].Indices[1] - links.Urls[urlSuffix].Indices[0] - 1;
                    urlSuffix++;
                }

                untreatedHashtagExist = hashtagSuffix < links.Hashtags.Count;
                untreatedMentionExist = mentionSuffix < links.Mentions.Count;
                untreatedUrlExist     = urlSuffix < links.Urls.Count;
            }

            if (LengthInTextElements(links.Text) > treatedIndex + 1)
            {
                textBlock.Inlines.Add(new Run()
                {
                    Text = Escape(links.Text.Substring(treatedIndex + 1), links.Media)
                });
            }
        }