我有一个内容很多的FlowDocument
。我需要获取当前在可见区域的控件。
使用以下代码,我可以获得当前滚动位置。
DependencyObject obj = FlowDocumentScrollViewerCtrl;
do
{
if (VisualTreeHelper.GetChildrenCount(obj) > 0)
{
obj = VisualTreeHelper.GetChild(obj as Visual, 0);
}
}
while (!(obj is ScrollViewer));
ScrollViewer sv = obj as ScrollViewer;
如何在可见区域内获取控件?
答案 0 :(得分:0)
一种方法是使用VisualTreeHelper.GetChildrenCount
和VisualTreeHelper.GetChild()
以递归方式下降Visual树,并使用以下过程检查每个Visual:
new Rect(0, 0, visual.ActualWidth, visual.ActualHeight)
获取每个Visual的边界框。这将为您提供Visual坐标系中的边界框。visual.TransformToAncestor(viewer)
返回的转换将边界框转换为查看器的坐标系。这将告诉您可见区域中的所有视觉效果。如果您要映射到FrameworkContentElement
,例如<Paragraph>
,请查看您在树木漫步中遇到的ContentPresenter
的内容属性。
答案 1 :(得分:0)
感谢Ray的回答。我昨天在某些方面遵循了你的提示,这就是我的问题的工作代码:
public class FrameworkElementInfo
{
Point _position = new Point();
FrameworkElement _element = null;
public Point Position
{
get { return _position; }
set { _position = value; }
}
public FrameworkElement FrameworkElement
{
get { return _element; }
set { _element = value; }
}
}
public class ScrollViewPositionManager
{
ScrollViewer _scrollViewer = null;
List<FrameworkElementInfo> _elements = new List<FrameworkElementInfo>();
double _zoom = 100.0;
public ScrollViewPositionManager(ScrollViewer scrollViewer, double zoom)
{
_scrollViewer = scrollViewer;
_zoom = zoom;
}
public void RegisterElement(FrameworkElement element, Boolean registerOnly)
{
FrameworkElementInfo info = new FrameworkElementInfo();
if (!registerOnly) info.Position = CalculatePosition(element);
info.FrameworkElement = element;
_elements.Add(info);
}
public void RecalculatePositions()
{
int Counter = 0;
foreach(FrameworkElementInfo info in _elements)
{
Counter += 1;
info.Position = CalculatePosition(info.FrameworkElement);
}
}
public List<FrameworkElement> GetElementsInViewPort()
{
List<FrameworkElement> elements = new List<FrameworkElement>();
double verticalOffsetHigh = _scrollViewer.ViewportHeight + _scrollViewer.VerticalOffset;
foreach (FrameworkElementInfo info in _elements)
{
Point point = info.Position;
if (point.Y >= _scrollViewer.VerticalOffset &&
point.Y <= verticalOffsetHigh)
{
elements.Add(info.FrameworkElement);
}
}
return elements;
}
private Point CalculatePosition(FrameworkElement element)
{
GeneralTransform elementTransform = element.TransformToAncestor(_scrollViewer);
Point elementPoint = elementTransform.Transform(new Point(0, 0));
Point transformedPoint = new Point(elementPoint.X, elementPoint.Y);
transformedPoint = GetZoomedPoint(elementPoint, _zoom, _scrollViewer.HorizontalOffset, _scrollViewer.VerticalOffset);
return transformedPoint;
}
static public Point GetZoomedPoint(Point unzoomedPoint, double zoom, double offsetX, double offsetY)
{
Point zoomedPoint = new Point();
double zoomFactor = 100.0 / zoom;
zoomedPoint.X = offsetX + unzoomedPoint.X * zoomFactor;
zoomedPoint.Y = offsetY + unzoomedPoint.Y * zoomFactor;
return zoomedPoint;
}
public int ElementCount
{
get { return _elements.Count; }
}
public FrameworkElement GetFirstElement()
{
FrameworkElement firstElement = null;
if(_elements.Count > 0) firstElement = _elements[0].FrameworkElement;
return firstElement;
}
public FrameworkElement GetLastElement()
{
FrameworkElement lastElement = null;
if (_elements.Count > 0) lastElement = _elements[_elements.Count-1].FrameworkElement;
return lastElement;
}
public FrameworkElement GetNextElement(FrameworkElement element)
{
FrameworkElement nextElement = null;
int index = GetElementIndex(element);
if(index != -1 && index != _elements.Count -1)
{
nextElement = _elements[index + 1].FrameworkElement;
}
return nextElement;
}
public FrameworkElement GetPreviousElement(FrameworkElement element)
{
FrameworkElement previousElement = null;
int index = GetElementIndex(element);
if (index > 1)
{
previousElement = _elements[index - 1].FrameworkElement;
}
return previousElement;
}
public int GetElementIndex(FrameworkElement element)
{
return _elements.FindIndex(
delegate(FrameworkElementInfo currentElement)
{
if(currentElement.FrameworkElement == element) return true;
return false;
}
);
}
}
我对感兴趣的元素使用注册函数,并且仅对它们起作用。我认为只需要一个FlowDocument缩放。此代码应适用于使用ScrollViewer的每个控件。 如果这是一个实用的解决方案,如果有人可以发表评论,我将不胜感激。