Can no longer reliably scroll FlowDocumentScrollViewer to bottom manually
- I've come across what might be a critical and fatal breaking change for my project.I asked a while ago about setting up a FlowDocumentScrollViewer as a chat buffer. By the nature of any kind of log buffers, the scroll viewer must always be scrolled to the bottom.This was doable several years ago; however, I'm not sure it's possible in the newest version.In the newest version, the flow document is rendered a little at a time, presumably to alleviate the time it takes to calculate the length of all the lines and the total length of the document. This has a side effect: since it takes several seconds to render the document asynchronously, if I call ScrollView.ScrollToBottom() in the meantime, that location will no longer be the bottom.This isn't a problem when it's assumed that you will not be as interested in the bottom of the document as you are the top. However, in any kind of log, the last line is of most interest, and so this is a critical problem.Is there any way to have the document render from the bottom up? Or at the very least, is there some way to determine when the document finishes rendering?If not, I will have to redesign my application to use some other kind of text buffer. Is there anything out there that is suitable for the purpose?Thanks in advance,Rei
- EditadoRei Miyasaka domingo, 25 de octubre de 2009 4:19some clarifications
Todas las respuestas
- Hi Rei Miyasaka,
Sorry for late reponse.
-->Is there any way to have the document render from the bottom up?
Based on my experience, there is no build-in way to do such a task, if you really want to do, i think you need to re-create a document render, but which does not seem to make much sense.
-->Or at the very least, is there some way to determine when the document finishes rendering?
When the Loaded event is raised, rendering is completely finished, so you can listen to Loaded event.
Thanks.
Sincerely.
Jim Zhou -MSFT- Propuesto como respuestaVaibhav S. Dabhade viernes, 30 de octubre de 2009 10:46
- Votado como útilRei Miyasaka viernes, 30 de octubre de 2009 12:45
- Thanks for your reply.Unfortunately, that doesn't work. The Loaded event fires both on the document as well as the viewer long before all the text actually shows up. Also, either way, this would only work on the first time the document is loaded, not when the document is re-rendered due to a change in width.
- Hi Rei Miyasaka,
-->this would only work on the first time the document is loaded, not when the document is re-rendered due to a change in width.
You are right, the loaded event only raise once in the lifetime of control. Based on my understanding, since you are tracking the rending changes, you can hoop up the SizeChanged and LayoutUpdated event, LayoutUpdated occurs when the layout of various visual elements associated with the current element.
If you are still having any additional issues with this, please feel free to ask.
Thanks.
Sincerely.
Jim Zhou -MSFT- Desmarcado como respuestaRei Miyasaka miércoles, 04 de noviembre de 2009 17:29
- Marcado como respuestaJim Zhou - MSFTModeradormiércoles, 04 de noviembre de 2009 8:23
- Hi Jim,Unfortunately this still does not solve the problem. It still does not serve as a way to know when the document finishes rendering. The rendering is asynchronous, so there is a race condition.Unfortunately my home computer is unavailable at the time due to a fire, but if you can, could you please try rendering about a thousand lines worth of text and scrolling to the bottom programmatically?Thanks,Rei
Hi Rei Miyasaka,
-->could you please try rendering about a thousand lines worth of text and scrolling to the bottom programmatically?
Since FlowDocumentScrollViewer does not expose a ScrollToEnd method directly, so we can first get the inside ScrollViewer control, then invoke its ScrollEnd metod to scroll the content to the end. The following method provide the functionality to get a element with special type in the visual tree.
Code snippet:
public List<T> GetChildrenOfType<T>(DependencyObject parent) where T : DependencyObject{
List<T> list = new List<T>();
int childCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
//get the current child
if (child is T) list.Add((T)child);
//if it is of type that you are looking for, then add it to the list
list.AddRange(GetChildrenOfType<T>(child)); // on that get a list of children that it has.
}
return list;
}
Thanks.
Sincerely.
Jim Zhou -MSFT- Hi Jim, that still isn't the problem.Unfortunately this still does not solve the problem. It still does not serve as a way to know when the document finishes rendering. The rendering is asynchronous, so there is a race condition.

