修剪/裁剪双方指定的文本

时间:2017-08-01 13:36:37

标签: c# wpf textblock

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

想象一下这样的文字:

  

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

关键字:

  

iscing

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

  

consectetur adip iscing elit

或(更好)

  

... consectetur adip iscing elit ...

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

我们使用MVVM模式。有没有人有一个有效的解决方案?非常感谢

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

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

编辑3:再次清楚 - 假设你在应用程序(文档)中有一些大文本和其他应用程序组件,如TextBlock,从大文本中显示搜索的关键字,并带有一些单词,以便用户可以获取上下文。 Textblock可以在运行时调整大小,因此它应该显示更多单词(基于大小)。理想情况下,关键字应该位于Textblock中间的某个位置。

2 个答案:

答案 0 :(得分:2)

此功能按您的要求执行:

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工具包中的等效项。

答案 1 :(得分:0)

Databind跟随文本块到适当的属性。

<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 SearchResult
{
      public PrecedingText { get; set; }
      public SearchText { get; set; }
      public SucceedingText { get; set; }
}