티스토리 뷰

반응형

TextBlock에 출력된 내용 중 내가 검색한 키워드의 위치를 표시하는 기능이 필요할 때가 있습니다.

그런데, 이 기능은 Behavior를 이용해서 붙일 수가 없습니다. 왜냐하면 TextBlock은 BehaviorCollection을 지원하지 않기 때문입니다.

저도 몰라서 Behavior를 만들어서 붙이려....ㅎㅎ

1. AttachedProperty 이용하기

이 기능을 구현하는 가장 쉬운 방법은 AttachedProperty를 이용하는 것입니다.

AttachedProperty를 이용하기 위해서 아래 클래스를 추가합니다.

/// <summary>
/// Text Extension
/// </summary>
public static class TextExtension
{
    private static readonly SolidColorBrush _redColorBrush = new(Colors.Red);

    public static string GetKeyword(DependencyObject obj)
    {
        return (string)obj.GetValue(KeywordProperty);
    }

    public static void SetKeyword(DependencyObject obj, string value)
    {
        obj.SetValue(KeywordProperty, value);
    }

    /// <summary>
    /// Keyword
    /// </summary>
    public static readonly DependencyProperty KeywordProperty =
        DependencyProperty.RegisterAttached("Keyword", typeof(string), typeof(TextExtension), new PropertyMetadata(null, OnKeywordChanged));

    private static void OnKeywordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //TextBlock이 아니거나 문자열이 아니거나 빈문자열인 경우 나감
        if (d is not TextBlock textBlock || string.IsNullOrWhiteSpace(textBlock.Text) || e.NewValue is not string keyword)
        {
            return;
        }
        try
        {
            string backupText = textBlock.Text;
            //첫번째 키워드 위치 저장 (1개의 키워드 위치만 찾아서 표시합니다)
            //이 내용 참고하면 전체 텍스트에서 검색해서 출력하는 것도 가능합니다.
            int index = backupText.IndexOf(keyword, StringComparison.OrdinalIgnoreCase);
            if (index == -1)
            {
                return;
            }
            string preText = backupText[..index];
            string keywordText = backupText.Substring(index, keyword.Length);
            string postText = backupText[(index + keyword.Length)..];
            textBlock.Inlines.Clear();
            textBlock.Inlines.Add(preText);
            //빨간색 글씨 표시
            textBlock.Inlines.Add(new Run(keywordText)
            {
                Foreground = _redColorBrush
            });
            textBlock.Inlines.Add(postText);
        }
        catch (Exception)
        {
            throw;
        }
    }
}

2. XAML에서 사용하기

TextExtension 클래스를 이용하기 위해서는 namespace를 먼저 추가해줘야 합니다.

xmlns:ext="clr-namespace:KeywordSample.Extensions"

그리고 TextBlock에 붙여서 사용합니다.

ext:TextExtension.Keyword="{Binding Keyword}"

<TextBlock
    Grid.Row="1"
    ext:TextExtension.Keyword="{Binding Keyword}"
    TextWrapping="Wrap">
    Methods
    We trained this model using Reinforcement Learning from Human Feedback (RLHF), 
    To create a reward model for reinforcement learning, we needed to collect comparison
</TextBlock>

3. 동작

바로 위에 TextBox에서 Keyword가 입력되면, 바로 아래로 전달되고, 키워드가 변경되면, TextBlock의 Text 프로퍼티의 값을 키워드랑 비교해서 글씨를 출력하게 됩니다.

참 쉽죠?

 

4. 소스

WpfTest/KeywordSample at master · kaki104/WpfTest (github.com)

 

GitHub - kaki104/WpfTest

Contribute to kaki104/WpfTest development by creating an account on GitHub.

github.com

이 소스 참고해서 전체 택스트에서 키워드를 모두 찾아서 표시하면 더 좋을 것 같네요~

반응형
댓글