2009-11-16 4 views
1

나는 내용이 많은 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

한 가지 방법은 재귀 적으로이 절차를 사용하여 각 시각을 VisualTreeHelper.GetChildrenCountVisualTreeHelper.GetChild()를 사용하여 시각적 트리를 내려하고 확인하는 것입니다 :

  1. 이 코드에 흥미없는 그 어떤 시각을 던져를 (예를 들어, 당신은 단지에 대해 신경 수 있습니다 컨트롤)
  2. new Rect(0, 0, visual.ActualWidth, visual.ActualHeight)을 사용하여 각 시각의 경계 상자를 가져옵니다. 그러면 Visual의 좌표계에서 테두리 상자가 나타납니다.
  3. visual.TransformToAncestor(viewer)이 반환하는 변환을 사용하여 경계 상자를 뷰어의 좌표계로 변형합니다.
  4. 변환 된 비주얼의 경계 상자가 뷰어의 경계 상자와 교차하는지 확인하십시오. 시각적 경계 상자 모서리의 최소 및 최대 X와 Y를 취하여 한 번에 하나의 축을 비교하면 대략적인 검사를 수행 할 수 있습니다. 이것은 전체 직사각형 교차점보다 쉽기 때문에 대부분의 목적을 위해 사용해야합니다.

이것은 당신에게 가시 영역에있는 모든 영상을 말할 것이다. <Paragraph>과 같이 FrameworkContentElement으로 매핑하려면 트리에서 가로 질러 실행하는 ContentPresenter의 Content 속성을 확인하십시오.

0

답장을 보내 주셔서 감사합니다. 나는 몇 가지 포인트에서 끝 어제를 따라 내 문제에 대한 작동 코드를 먹으 렴 :

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를 사용하는 모든 컨트롤에서 작동해야합니다. 실용적인 솔루션이라면 누구든지이 점을 언급 해 주시면 감사하겠습니다.

관련 문제