Trim/Crop 双方指定文字

Trim/Crop specified text from both sides

我需要从可能很长的文本中裁剪并显示指定的关键字(周围有一些词)。

想象一下这样的文本:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua

关键字:

iscing

我的目标是在一些宽度非常有限的 TextBlock 中显示如下内容:

consectetur adipiscing elit

或(更好)

...consectetur adipiscing elit...

关键字周围的字数应基于 space 可用。

我们使用 MVVM 模式。有人对此有可行的解决方案吗?非常感谢

编辑:我现在不想突出关键字。

编辑 2:为了简单起见,假设我们只想显示第一次出现的 "iscing" 关键字。

编辑 3:再次弄清楚 - 假设您在应用程序(文档)和应用程序的其他组件(如 TextBlock)中有一些大文本显示从大文本中搜索到的关键字,周围有一些词,以便用户可以获得上下文.文本块可以在运行时调整大小,因此它应该显示更多的单词(基于大小)。关键字最好位于文本块中间的某个位置。

此函数执行您的要求:

public string Truncate(string input, string match, int nbCharMaxBefore, int nbCharMaxAfter)
{  
    var inputSplit = input.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);

    var index = 0;
    while (index < inputSplit.Length)
    {
        if (inputSplit[index].Contains(match)) break;

        index++;
    }

    if (index == inputSplit.Length)
    {
        // No match
        return String.Empty;
    }

    // Adds all the words before the match as long as the sum of all the words is not greater than the specified limit
    var previousWords = new List<string>();
    var i = index - 1;
    while (i >= 0)
    {
        var previousWord = inputSplit[i];

        if (previousWord.Length + previousWords.Sum(w => w.Length) < nbCharMaxBefore)
        {
            previousWords.Insert(0, previousWord);
        }
        else
        {
            break;
        }

        i--;
    }

    // Adds all the words after the match as long as the sum of all the words is not greater than the specified limit
    var nextWords = new List<string>();
    i = index + 1;
    while (i < inputSplit.Length)
    {
        var nextWord = inputSplit[i].TrimEnd(',');

        if (nextWord.Length + nextWords.Sum(w => w.Length) < nbCharMaxAfter)
        {
            nextWords.Add(nextWord);
        }
        else
        {
            break;
        }

        i++;
    }

    var prev = String.Join(" ", previousWords);
    var next = String.Join(" ", nextWords);

    return $"...{prev} {inputSplit[index]} {next}...";
}

你可以这样使用它:

var input = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua";
var match = "iscing";
var nbCharMaxBefore = 15;
var nbCharMaxAfter = 5;

var truncatedStr = Truncate(input, match, nbCharBefore, nbCharAfter); // ...consectetur adipiscing elit...

关于 MVVM 方式,考虑到您绑定的 属性 是 MyText,只需像这样绑定另一个 属性:

public string MyTruncatedText
{
    get { return Truncate(this.MyText, this.MyMatch, this.NbCharBefore, this.NbCharAfter); }
}

最后,在 MyText 的 setter 中,您想调用 NotifyPropertyChanges(nameof(MyTruncatedProperty)) 或 MVVM 工具包中的等效项。

将文本块后的数据绑定到适当的属性。

<TextBlock>
    <Run x:Name="pre" Text="{Binding PrecedingText}" />
    <Run x:Name="search" Text="{Binding SearchText}" FontWeight="Bold" />
    <Run x:Name="succeeding" Text="{Binding SucceedingText}" />
</TextBlock>

使用以下视图模型class。

class SearchResult
{
      public PrecedingText { get; set; }
      public SearchText { get; set; }
      public SucceedingText { get; set; }
}