如何使 Silverlight ScrollViewer 滚动以显示具有焦点的子控件?

发布于 2024-07-30 05:49:29 字数 255 浏览 3 评论 0原文

我有一个 ScrollViewer,其中包含一个带有多个控件的网格。 用户可以通过 Tab 键浏览控件,但最终他们会切换到不在视图中的控件 - 因此他们必须手动滚动以使控件再次可见。

有没有办法让 ScrollViewer 自动滚动,以便焦点控件始终可见。 如果做不到这一点,有什么方法可以使这项工作成功,而不是在每个控件上侦听 GotFocus 事件,然后滚动 ScrollViewer 以使控件可见?

目前我使用的是Silverlight 2。

I have a ScrollViewer which contains a Grid with multiple controls in it. The user can tab through the controls, but eventually they tab to a control that isn't in view - so they have to manully scroll to make the control visible again.

Is there any way to make the ScrollViewer scroll automatically so that the focussed control is always visible. Failing that, is there any way I can make this work, short of listening to a GotFocus event on every control and then scrolling the ScrollViewer to make the control visible?

At present I'm using Silverlight 2.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

疯到世界奔溃 2024-08-06 05:49:29

我使用 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);
}

我所做的是单击 Button #1 和选项卡,直到到达按钮#20。 这对我有用。 尝试一下,让我知道它对您有何作用。

I tested this using Silverlight 3. I am not sure about SL2.

This is my 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>

And this is the code-behind:

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);
}

What I did was to click on Button #1 and tab until I get to Button #20. It worked for me. Give it a try and let me know how it works for you.

静若繁花 2024-08-06 05:49:29

silverlight工具包包含一个方法“ScrollIntoView”。

添加对 System.Windows.Controls.Toolkit.dll 的引用,您应该能够使用下面的代码。

scrollViewer.ScrollIntoView(control);

The silverlight toolkit contains a method "ScrollIntoView".

Add a reference to System.Windows.Controls.Toolkit.dll ans you should be able to use the code below.

scrollViewer.ScrollIntoView(control);

止于盛夏 2024-08-06 05:49:29

只是轻微的增强。 顺便说一句,仍然需要为 Silverlight 4 执行此操作。
您可以处理滚动查看器本身的 GotFocus 并仅实现一次,而不是每个控件的 GotFocus。

 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
        }

Just a slight enhancement. Still need to do this for Silverlight 4 by the way.
Instead of GotFocus for each control you can handle the GotFocus of the scrollviewer itself and implement it just once.

 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
        }
卸妝后依然美 2024-08-06 05:49:29

在基里尔上面的回答的帮助下,我成功了。 一般情况是我的应用程序中有用户可定义的表单,并且此代码用于在表单上呈现控件。

我的一般策略是将控件添加到 Grid,然后使用 VisualTreeHelper 查找 ScrollViewer 的所有子级,并向每个控件添加 GotFocus 事件处理程序。

当控件获得焦点时,再次使用 VisualTreeHelper,我在可视化树中搜索以查找其父级是由 ScrollViewer 滚动的 Grid 的控件。 然后我滚动 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 类添加了一些有用的搜索功能。

I got this to work, with help of Kiril's answer above. The general context of this is that I have user-defineable forms in my application, and this code is used for rendering the controls on a form.

My general strategy was to add my controls to a Grid, then find all the children of the ScrollViewer using VisualTreeHelper, and add a GotFocus event handler to each control.

When the control gets focus, again using VisualTreeHelper, I search up the visual tree to find the control whose parent is the Grid that is being scrolled by the ScrollViewer. Then I scroll the ScrollViewer to make the control visible.

Here's the code (gridRender is the Grid that the controls are added to):

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);
    }
}

Note: the VisualTreeHelperUtil class is my own class that adds some useful searching functionality to the VisualTreeHelper class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文