كيف يمكنني جعل Silverlight ScrollViewer يقوم بالتمرير لإظهار عنصر تحكم الطفل مع التركيز؟

StackOverflow https://stackoverflow.com/questions/1225318

  •  22-07-2019
  •  | 
  •  

سؤال

لدي ScrollViewer الذي يحتوي على شبكة بها عناصر تحكم متعددة.يمكن للمستخدم التنقل بين عناصر التحكم، لكنه في النهاية ينتقل إلى عنصر تحكم غير معروض - لذلك يتعين عليه التمرير يدويًا لجعل عنصر التحكم مرئيًا مرة أخرى.

هل هناك أي طريقة لجعل ScrollViewer يتم تمريره تلقائيًا بحيث يكون عنصر التحكم الذي تم التركيز عليه مرئيًا دائمًا.في حالة الفشل في ذلك، هل هناك أي طريقة يمكنني من خلالها تنفيذ هذا العمل، باستثناء الاستماع إلى حدث GotFocus على كل عنصر تحكم ثم تمرير ScrollViewer لجعل عنصر التحكم مرئيًا؟

حاليًا أستخدم Silverlight 2.

هل كانت مفيدة؟

المحلول

لقد اختبرت هذا باستخدام Silverlight 3.لست متأكدا من SL2.

هذا هو XAML الخاص بي:

<ScrollViewer Height="200" Width="200" KeyUp="ScrollViewer_KeyUp">
    <StackPanel>
        <Button Content="1" Height="20" />
        <Button Content="2" Height="20" />
        <Button Content="3" Height="20" />
        <Button Content="4" Height="20" />
        <Button Content="5" Height="20" />
        <Button Content="6" Height="20" />
        <Button Content="7" Height="20" />
        <Button Content="8" Height="20" />
        <Button Content="9" Height="20" />
    <Button Content="10" Height="20" />
        <Button Content="11" Height="20" />
        <Button Content="12" Height="20" />
        <Button Content="13" Height="20" />
        <Button Content="14" Height="20" />
        <Button Content="15" Height="20" />
        <Button Content="16" Height="20" />
        <Button Content="17" Height="20" />
        <Button Content="18" Height="20" />
        <Button Content="19" Height="20" />
        <Button Content="20" Height="20" />
    </StackPanel>
</ScrollViewer>

وهذا هو الكود الخلفي:

private void ScrollViewer_KeyUp(object sender, KeyEventArgs e)
{
    ScrollViewer scrollViewer = sender as ScrollViewer;
    FrameworkElement focusedElement = FocusManager.GetFocusedElement() as FrameworkElement;
    GeneralTransform focusedVisualTransform = focusedElement.TransformToVisual(scrollViewer);
    Rect rectangle = focusedVisualTransform.TransformBounds(new Rect(new Point(focusedElement.Margin.Left, focusedElement.Margin.Top), focusedElement.RenderSize));
    double newOffset = scrollViewer.VerticalOffset + (rectangle.Bottom - scrollViewer.ViewportHeight);
    scrollViewer.ScrollToVerticalOffset(newOffset);
}

ما فعلته هو النقر على الزر رقم 1 وعلامة التبويب حتى أصل إلى الزر رقم 20.عملت معي.جربها واسمحوا لي أن أعرف كيف يعمل بالنسبة لك.

نصائح أخرى

ومجموعة أدوات سيلفرلايت يحتوي على طريقة "ScrollIntoView".

وإضافة مرجع إلى System.Windows.Controls.Toolkit.dll الجواب يجب أن تكون قادرا على استخدام الكود بالأسفل.

وscrollViewer.ScrollIntoView(control);

ومجرد زيادة طفيفة. لا تزال هناك حاجة للقيام بذلك ل Silverlight 4 من جانب الطريق. بدلا من GotFocus لكل عنصر تحكم يمكنك التعامل مع GotFocus من scrollviewer نفسها وتنفيذه مرة واحدة فقط.

 private void _ScrollViewer_GotFocus(object sender, RoutedEventArgs e)
        {
            FrameworkElement element = e.OriginalSource as FrameworkElement;

            if (element != null)
            {
                ScrollViewer scrollViewer = sender as ScrollViewer;
                scrollViewer.ScrollToVerticalOffset(GetVerticalOffset(element, scrollViewer));
            }

        }

        private double GetVerticalOffset(FrameworkElement child, ScrollViewer scrollViewer)
        {
            // Ensure the control is scrolled into view in the ScrollViewer. 
            GeneralTransform focusedVisualTransform = child.TransformToVisual(scrollViewer);
            Point topLeft = focusedVisualTransform.Transform(new Point(child.Margin.Left, child.Margin.Top));
            Rect rectangle = new Rect(topLeft, child.RenderSize);
            double newOffset = scrollViewer.VerticalOffset + (rectangle.Bottom - scrollViewer.ViewportHeight);
            return newOffset < 0 ? 0 : newOffset; // no use returning negative offset
        }

لقد نجحت في هذا بمساعدة إجابة كيريل أعلاه.السياق العام لهذا هو أن لدي نماذج يمكن تعريفها من قبل المستخدم في تطبيقي، ويتم استخدام هذا الرمز لعرض عناصر التحكم في النموذج.

كانت استراتيجيتي العامة هي إضافة عناصر التحكم الخاصة بي إلى الشبكة، ثم العثور على جميع عناصر ScrollViewer الفرعية باستخدام VisualTreeHelper، وإضافة معالج حدث GotFocus إلى كل عنصر تحكم.

عندما يتم التركيز على عنصر التحكم، مرة أخرى باستخدام VisualTreeHelper، أقوم بالبحث في الشجرة المرئية للعثور على عنصر التحكم الذي يكون أصله هو الشبكة التي يتم تمريرها بواسطة ScrollViewer.ثم أقوم بتمرير ScrollViewer لجعل عنصر التحكم مرئيًا.

إليك الكود (gridRender هو الشبكة التي تمت إضافة عناصر التحكم إليها):

private void AfterFormRendered()
{
    var controls = VisualTreeHelperUtil.FindChildren<Control>(gridRender);
    foreach (var ctrl in controls)
    {
        ctrl.GotFocus += CtrlGotFocus;
    }
}

private void CtrlGotFocus(object sender, RoutedEventArgs e)
{
    var ctrl = sender as Control;
    var gridChildControl = VisualTreeHelperUtil.FindParentWithParent(ctrl, gridRender) as FrameworkElement;

    if (gridChildControl != null)
    {
        // Ensure the control is scrolled into view in the ScrollViewer.
        GeneralTransform focusedVisualTransform = gridChildControl.TransformToVisual(scrollViewer);
        Point topLeft = focusedVisualTransform.Transform(new Point(gridChildControl.Margin.Left, gridChildControl.Margin.Top));
        Rect rectangle = new Rect(topLeft, gridChildControl.RenderSize);
        double newOffset = scrollViewer.VerticalOffset + (rectangle.Bottom - scrollViewer.ViewportHeight);    

        scrollViewer.ScrollToVerticalOffset(newOffset);
    }
}

ملحوظة:فئة VisualTreeHelperUtil هي فئتي الخاصة التي تضيف بعض وظائف البحث المفيدة إلى فئة VisualTreeHelper.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top