【问题标题】:Dynamically formatting Text items in a ListBox in XAML在 XAML 中动态格式化 ListBox 中的文本项
【发布时间】:2020-04-28 14:58:30
【问题描述】:

我正在使用 Caliburn Micro,并且有一个 ListBox 可以显示我从 ViewModel 绑定到它的项目列表。

但是,我现在正在研究如何动态设置每个 ListItem 的格式,即在我的例子中,每个字符串最多可以有 N 个介于两个标记之间的值,我需要将它们格式化为粗体。

我能够将文本解析成一个列表,然后标记哪些单词或单词块需要格式化,哪些不需要,但是我不知道如何在我的 ListBox 中显示它。环顾四周,我看到有些人建议使用可以解析文本字符串的转换器?

我的 XAML 目前的列表框看起来像 - 当我只需要格式化一个关键字时,这是有效的,但后来发现单个字符串中可能出现多次,因此无法预测结构没有了。

<ListBox ItemsSource="{Binding HighlightList}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock>
                <Run Text="{Binding Path=mStartText}"/>
                <Run Text="{Binding Path=mBoldText}"/>
                <Run Text="{Binding Path=mEndText}"/>
            </TextBlock>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

还有其他人能够实现类似的目标吗?提前感谢您的任何提示!

编辑:

所以,为了更清楚起见,假设我有两个字符串:

字符串 1 - “这是一个 测试 字符串”

String 2 - "这个 is 也是一个 Test 字符串

我要做的是在 ListBox 中显示上面的字符串,其中包含在 EM 标记中的字符串(上面示例中的斜体)为粗体和红色字体颜色。

我现在所做的是创建一个对象列表,每个对象都有两个变量 - 字符串内容和字符串类型(突出显示或未突出显示)并解析每个字符串并将其分解,以便我标记它的哪些部分可以按原样打印,需要以高亮格式打印。

视图模型:

    public ObservableCollection<HighlightItem> HighlightList
    {
        get
        {
            return _highlightList;
        }
        set
        {
            _highlightList = value;
            NotifyOfPropertyChange(() => HighlightList);
        }
    }

public void ParseHighlights()
        {
            ObservableCollection<HighlightItem> hlList = new ObservableCollection<HighlightItem>();

            string START_HL_TOKEN = "<em>";
            string END_HL_TOKEN = "</em>";

            if (_documentSnippets.Count > 0)
            {
                foreach (var hlItem in _documentSnippets.Snippets["text"])
                {
                    // Remove tab characters
                    string temp = hlItem.Replace("\t", "");

                    // Remove multiple newline characters and replace with a single one
                    Regex regex = new Regex("(\\n){2,}");

                    string clean_temp = regex.Replace(temp, "\n");
                    string startText = "", hlText = "", endText = "";
                    int start_idx = 0;
                    int end_idx = 0;
                    List<string> stringTokenized = new List<string>();

// THIS BELOW IS PART OF MY NEW APPROACH
                    while(start_idx != clean_temp.Length)
                    {
                        end_idx = clean_temp.IndexOf(START_HL_TOKEN, start_idx);

                        // Highlight token is at the start
                        if(end_idx == 0)
                        {
                            start_idx = end_idx;
                            end_idx = clean_temp.IndexOf(END_HL_TOKEN, start_idx);
                            stringTokenized.Add(clean_temp.Substring(start_idx + 4, end_idx - start_idx));

                            // Move pointer to start of next section, keeping in mind the length of the END token
                            start_idx = end_idx + 4;
                        }
                        else if(end_idx == -1)
                        {
                            end_idx = clean_temp.Length;
                            stringTokenized.Add(clean_temp.Substring(start_idx, end_idx - start_idx));
                            start_idx = end_idx;
                        }
                        else
                        {
                            stringTokenized.Add(clean_temp.Substring(start_idx, end_idx - start_idx));

                            start_idx = end_idx;
                            end_idx = clean_temp.IndexOf(END_HL_TOKEN, start_idx);
                            stringTokenized.Add(clean_temp.Substring(start_idx + 4, end_idx - start_idx));

                            // Move pointer to start of next section
                            start_idx = end_idx + 4;
                        }
                    }
// END OF MY NEW APPROACH

                    // Token is at the beginning of the snippet
                    if (hlItem.IndexOf(START_HL_TOKEN) == 0)
                    {
                        hlText = clean_temp.Substring(clean_temp.IndexOf(START_HL_TOKEN) + START_HL_TOKEN.Length,
                                                   clean_temp.IndexOf(END_HL_TOKEN) - START_HL_TOKEN.Length);

                        endText = clean_temp.Substring(clean_temp.IndexOf(END_HL_TOKEN) + END_HL_TOKEN.Length,
                                                   clean_temp.Length - (clean_temp.IndexOf(END_HL_TOKEN) + END_HL_TOKEN.Length));
                    }
                    // Token is at the end of the snippet
                    else if (clean_temp.IndexOf(END_HL_TOKEN) + END_HL_TOKEN.Length == clean_temp.Length)
                    {
                        startText = clean_temp.Substring(0,
                                                     clean_temp.Length - clean_temp.IndexOf(START_HL_TOKEN));
                        hlText = clean_temp.Substring(clean_temp.IndexOf(START_HL_TOKEN),
                                                  clean_temp.Length - clean_temp.IndexOf(START_HL_TOKEN));
                    }
                    // Token is in the middle of the snippet
                    else
                    {
                        startText = clean_temp.Substring(0,
                                                     clean_temp.IndexOf(START_HL_TOKEN));

                        hlText = clean_temp.Substring(clean_temp.IndexOf(START_HL_TOKEN) + START_HL_TOKEN.Length,
                                                  clean_temp.IndexOf(END_HL_TOKEN) - clean_temp.IndexOf(START_HL_TOKEN) - (END_HL_TOKEN.Length - 1));

                        endText = clean_temp.Substring(clean_temp.IndexOf(END_HL_TOKEN) + END_HL_TOKEN.Length,
                                                   clean_temp.Length - clean_temp.IndexOf(END_HL_TOKEN) - END_HL_TOKEN.Length);
                    }

                    HighlightItem snippet = new HighlightItem(startText, hlText, endText);
                    hlList.Add(snippet);
                }

                HighlightList = hlList;
            }

        }

所以在上面的模型中,我有我的旧方法,我假设字符串中只有一个标签,但是当我意识到有时有多个标签时,我开始了一种新方法来构建字符串的列表表示,标记哪些部分需要正常打印,哪些需要打印突出显示。

还有我的命名标准,大约一个月前才开始 WPF 和 C#,所以还不太了解所有命名约定,抱歉!

【问题讨论】:

  • 您可以为每个项目使用 rtf/html 而不是纯文本。或者在视图中有一些动态生成 Run 元素集合的逻辑。你已经here了吗?
  • 当你说N值时,你的意思是更多的属性吗?您的模型的代码示例也将对我们有所帮助。另外,您为什么将属性命名为字段?
  • 您好,添加了包含更多信息的更新 - 希望目前结合我的两种方法不会太混乱!我也会研究一下 RTF 控件!

标签: c# wpf xaml caliburn.micro


【解决方案1】:

根据 Sinatr 的提示,使用自定义附加属性对我有用,我找到了以下文章:WPF TextBlock formatting bold from string property

在我能够提供嵌入了标记的字符串之后,它们将被正确打印!感谢您的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    • 2019-10-23
    • 1970-01-01
    • 2011-10-28
    相关资源
    最近更新 更多