文章目录
- 目录提取
- 列表控件
- 整改
txt阅读器系列:
- 需求分析和文件读写
- 目录提取类💎列表控件与目录
目录提取
在实现标题类之后,就可以实战演习一番。首先在mainWindow
中添加Catalog
类
public Catalog catalog;
然后更改
然后在标题栏中添加目录
按钮,并绑定btnCatalog_Click
事件,其内容为
private void btnCatalog_Click(object sender, RoutedEventArgs e)
{
if (txt.Text.Length == 0)
return;
catalog = new Catalog(txt.Text, true);
}
当然,生成目录的方法最终一定要设置为可选参量,但目前作为功能测试阶段,可以直接根据我们用来测试的文本文档来直接确定,选择true
。
然后为了验证这种查找目录方法的可靠性,在右侧栏中添加一个TextBox
,名为txtInfo
,然后将生成的目录添加到txtInfo
中,从而完整的btnCatalog_Click
如下
private void btnCatalog_Click(object sender, RoutedEventArgs e)
{
if (txt.Text.Length == 0)
return;
catalog = new Catalog(txt.Text, true);
foreach (var item in catalog.secs)
txtInfo.AppendText($"{item.title}\r\n");
}
效果为
很明显这里出现了一个bug
,即序言
作为目录被挑选了两次,为了避免这种情况,为Catalog
类添加一个新的判定方法
public bool Contains(string title)
{
foreach (var sec in secs)
if(sec.title == title.Trim())
return true;
return false;
}
并在extractCatalog
中添加
if (Contains(p))
break;
列表控件
将目录打印出来其实并没有什么用,我们的目的是点击目录然后可以跳转,一个比较直接的方案是,把目录映射到一个列表控件中。故而在左下角的ScollViewer
中添加一个
<ListBox x:Name="lvCatalog"/>
,然后修改btnCatalog_Click
,内容变为下面这样
private void btnCatalog_Click(object sender, RoutedEventArgs e)
{
if (txt.Text.Length == 0)
return;
catalog = new Catalog(txt.Text, true);
lvCatalog.Items.Clear();
foreach (var item in catalog.secs)
lvCatalog.Items.Add(item.title);
}
其中,lvCatalog.Items.Clear()
用于清空列表,然后下面会循环填入目录的标题。
最后,就是真正实现目录导航功能的关键,注册列表控件的点击事件,然后调用生成好的目录进行跳转
private void lvCatalog_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int i = lvCatalog.SelectedIndex;
int ed = (i+1) < catalog.secs.Count ? catalog.secs[i + 1].location : doc.Length;
txt.Text = doc[catalog.secs[i].location..ed];
txt.ScrollToHome();
}
最后效果如下
整改
目前尽管已经实现了基本功能,但是有一个尴尬的问题,即目录跳转过程中,直接把目录本身跳过去了。为此,可修改Catalog
类的extractCatalog
方法——新建标题之前,先添加一个目录
标题。
public void extractCatalog(string txt)
{
int i = 0, num = 0; //i是章节号;num是章节位置
secs.Add(new Section(i++, "目录", 0));
foreach (var p in txt.Split("\r\n"))
{
num += p.Length;
if (p.Trim().Length == 0)
continue;
if (!isSection(p))
break;
if (Contains(p))
break;
secs.Add(new Section(i++, p, txt, num * 2));
}
}