private void ScrollLine(ScrollElem sel)
 {
     sel.Viewer.Dispatcher.Invoke(DispatcherPriority.Normal,
                                  (ParameterizedThreadStart) delegate(object objP)
     {
         ScrollElem e = objP as ScrollElem;
         if (e == null || e.Viewer.VerticalOffset >= e.MaxToScroll)
         {
             return;
         }
         e.Viewer.LineDown();
         Thread thr = new Thread(new ParameterizedThreadStart(delegate(object obj)
         {
             ScrollElem s = (ScrollElem)obj;
             Thread.Sleep(30);
             ScrollLine(s);
         }));
         thr.Start(e);
     }, sel);
 }
        private bool ScrollNext(FrameworkElement fel)
        {
            int        nMx = 0;
            Visibility vis;

            if (fel.Dispatcher.CheckAccess())
            {
                vis = fel.Visibility;
            }
            else
            {
                vis = (Visibility)fel.Dispatcher.Invoke(DispatcherPriority.Send,
                                                        (Func <FrameworkElement, Visibility>)(f => f.Visibility), fel);
            }

            if (vis != System.Windows.Visibility.Visible)
            {
                return(false);
            }

            PhotoControl pc = fel as PhotoControl;

            if (pc != null)
            {
                if (pc.Dispatcher.CheckAccess())
                {
                    return(pc.ScrollToNext());
                }
                else
                {
                    return((bool)pc.Dispatcher.Invoke(DispatcherPriority.Send,
                                                      (Func <PhotoControl, bool>)(p => p.ScrollToNext()), pc));
                }
            }
            ScrollViewer scv = fel as ScrollViewer;

            if (scv == null)
            {
                return(false);
            }
            double curScr;

            if (scv.Dispatcher.CheckAccess())
            {
                curScr = scv.VerticalOffset;
            }
            else
            {
                curScr = (double)scv.Dispatcher.Invoke(DispatcherPriority.Send,
                                                       (Func <ScrollViewer, double>)(lamArg => lamArg.VerticalOffset), scv);
            }



            var q = scv.Dispatcher.BeginInvoke(DispatcherPriority.Send,
                                               (Func <ScrollViewer, double, bool>) delegate(ScrollViewer sv, double pos)
            {
                sv.BeginInit();
                sv.PageDown();
                sv.EndInit();
                return(true);
            }, scv, new object[] { 0.0 });

            nMx = 0;
            while (q.Status != DispatcherOperationStatus.Completed && nMx < 1000)
            {
                nMx++;
                Thread.Sleep(2);
            }
            if (q.Status != DispatcherOperationStatus.Completed)
            {
                q.Abort();
                return(false);
            }

            double maxToScroll = (double)scv.Dispatcher.Invoke(
                DispatcherPriority.Send,
                (Func <ScrollViewer, double>)(lamArg => lamArg.VerticalOffset), scv);

            if (curScr >= maxToScroll)
            {
                return(false);
            }

            q = scv.Dispatcher.BeginInvoke(DispatcherPriority.Send,
                                           (Func <ScrollViewer, double, bool>) delegate(ScrollViewer sv, double pos)
            {
                sv.ScrollToVerticalOffset(pos);
                return(true);
            }, scv, new object[] { curScr });

            nMx = 0;
            while (q.Status != DispatcherOperationStatus.Completed && nMx < 1000)
            {
                Thread.Sleep(2);
                nMx++;
            }
            if (q.Status != DispatcherOperationStatus.Completed)
            {
                q.Abort();
                return(false);
            }

            var se = new ScrollElem(scv, maxToScroll);

            ScrollLine(se);
            return(true);
        }