这是一个抽象的问题,但我无法想到其他任何问题。
我有一个带有RichText编辑器的Windows应用商店应用(使用RichEditBox
控件)
这是一个极简主义的写作应用程序,我想添加一个功能,允许用户在文档中添加边距注释。用户可以在文档中的任何位置添加边距注释,然后将其保存到单独的文件中。当他们重新打开文档时,他们应该能够向上和向下滚动并在正确的位置查看边距注释。
那我该怎么做?我一直绞尽脑汁试图找出最好的方法来做到这一点。 RTF /文本文件不包含行号。我能想到的最安全的事情是计算项目的单词数量,因为即使编辑器改变宽度或字体大小,这也可以让我获得粗略的位置。但有两件事让我感到难过
假设我写了一个1000字的文件。我在400字的位置添加了一个注释。
1)如何将“400个字”映射到我的“边缘注释”网格中的垂直位置?我最好的想法:我创建了一个相同尺寸的不可见阴影RichEditBox,但高度可变。我把前400个单词放入其中,然后测量这个框的高度。我将此高度应用于相关注释(可能作为边距偏移)。我看到的这个问题是我可以想象我添加的笔记越来越慢。
2)我如何编辑?假设我回去并在我的笔记前添加200个单词,我的应用程序如何知道在某个点之前添加了多少个单词?并且不必用每次击键重新运行上面的代码,只是为了确保笔记的位置是正确的?
注意mods:如果这在另一个堆栈中更合适,请随意移动它。此外,目前还没有RichEditBox标签,因此如果代表高于1500的人想要创建它,那将非常感激。
答案 0 :(得分:0)
我的解决方案
最初,当我同步两个ScrollViewers
(一个用于编辑器,一个用于保证金清单),调整高度等位置时,事情变得非常复杂。最终我意识到我可以把我的保证金说明相同 ScrollViewer
中的列表和编辑器,而不必同步任何内容。
这是我的XAML。我删除了任何不相关的内容。
<ScrollViewer x:Name="EditorScroller"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid x:Name="MarginNotes" Grid.Column="0" HorizontalAlignment="Right"
Margin="0,0,20,0"></Grid>
<StackPanel Grid.Column="1">
<RichEditBox x:Name="MarginHelper" Opacity="0"
FontSize="{Binding FontSize}"></RichEditBox>
<!-- in a StackPanel so that the height is not set
note MarginHelper must have the exact
same Width and FontSize as the editor,
even though MarginHelper is not visible -->
</StackPanel>
<RichEditBox x:Name="editor" FontSize="{Binding FontSize}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
Grid.Column="1" Height="Auto" BorderThickness="0" />
</Grid>
</ScrollViewer>
请注意,MarginHelper
位于StackPanel
内。这意味着它不会伸展以填充Grid
,并且可用于确定内容的高度
当用户按下CTRL + M时,会出现一个对话框,允许他们输入注释。然后,下面的代码附上说明
private async Task AddMarginNote(string noteText)
{
// get current cursor position
int sPos = editor.Document.Selection.StartPosition;
// select everything from the start of the document to the current position
editor.Document.Selection.StartPosition = 0;
editor.Document.Selection.EndPosition = sPos;
// get selected text
string text = "";
editor.Document.Selection.GetText(TextGetOptions.None, out text);
// set MarginHelper text to selected text
MarginHelper.Document.SetText(TextSetOptions.None, text);
// reset the editor selection
editor.Document.Selection.StartPosition = sPos;
// measure height of MarginHelper
// (less 25 pixels, I'm not sure where this extra height is
// creeping in but its the only way to make this accurate)
double mHeight = MarginHelper.ActualHeight - 25;
// add a note to MarginNotes
TextBlock note = new TextBlock();
note.Text = noteText;
note.Foreground = new SolidColorBrush(Colors.White);
note.Margin = new Thickness { Top = mHeight };
MarginNotes.Children.Add(note);
// save note to db
// code here would store noteText along with text.Length for this document
}
我还没有添加代码来实际将这些笔记保存在任何地方,但我已经测试过成功加载它们,使用以下代码
private async void LoadNote(string noteText, int chars)
{
// set selection
editor.Document.Selection.StartPosition = 0;
editor.Document.Selection.EndPosition = chars;
// get text
string text = "";
editor.Document.Selection.GetText(TextGetOptions.None, out text);
// set MarginHelper text
MarginHelper.Document.SetText(TextSetOptions.None, text);
// measure height of MarginHelper
double mheight = MarginHelper.ActualHeight - 25;
// add a note to MarginNotes
TextBlock note = new TextBlock();
note.Text = noteText;
note.Foreground = new SolidColorBrush(Colors.White);
note.Margin = new Thickness { Top = mheight };
MarginNotes.Children.Add(note);
}
我仍然不确定这会如何扩展,但到目前为止它似乎对中小型文档表现得相当不错。
另外,在编辑文本时,我仍然没有弄清楚如何完全抵消保存的笔记,但是当我弄明白时,我会在这里发布结果
这对我的应用来说非常具体,但是稍后可能会对其他人派上用场,所以我发布了它。