【发布时间】: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