Come posso fare scorrere il SilverView ScrollViewer per mostrare un controllo figlio con lo stato attivo?

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

  •  22-07-2019
  •  | 
  •  

Domanda

Ho un ScrollViewer che contiene una griglia con più controlli al suo interno. L'utente può scorrere tra i controlli, ma alla fine può passare a un controllo che non è in vista, quindi deve scorrere manualmente per rendere nuovamente visibile il controllo.

Esiste un modo per far scorrere automaticamente ScrollViewer in modo che il controllo focalizzato sia sempre visibile. In caso contrario, c'è un modo per farlo funzionare, a meno di ascoltare un evento GotFocus su ogni controllo e quindi scorrere ScrollViewer per rendere visibile il controllo?

Attualmente sto usando Silverlight 2.

È stato utile?

Soluzione

Ho provato questo usando Silverlight 3. Non sono sicuro di SL2.

Questo è il mio 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>

E questo è il 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);
}

Quello che ho fatto è stato fare clic sul pulsante n. 1 e sulla scheda fino ad arrivare al pulsante n. 20. Ha funzionato per me. Provalo e fammi sapere come funziona per te.

Altri suggerimenti

Il toolkit silverlight contiene un metodo " ScrollIntoView " ;.

Aggiungi un riferimento a System.Windows.Controls.Toolkit.dll e dovresti essere in grado di usare il codice qui sotto.

scrollViewer.ScrollIntoView (controllo);

Solo un leggero miglioramento. A proposito, devo ancora farlo per Silverlight 4. Invece di GotFocus per ogni controllo, puoi gestire GotFocus dello scrollviewer stesso e implementarlo una sola volta.

 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
        }

L'ho fatto funzionare, con l'aiuto della risposta di Kiril sopra. Il contesto generale di ciò è che ho moduli definibili dall'utente nella mia applicazione e questo codice viene utilizzato per il rendering dei controlli in un modulo.

La mia strategia generale era quella di aggiungere i miei controlli a una griglia, quindi trovare tutti i figli di ScrollViewer usando VisualTreeHelper e aggiungere un gestore eventi GotFocus a ciascun controllo.

Quando il controllo diventa attivo, usando nuovamente VisualTreeHelper, cerco l'albero visivo per trovare il controllo il cui genitore è la Griglia che è stata fatta scorrere da ScrollViewer. Quindi faccio scorrere ScrollViewer per rendere visibile il controllo.

Ecco il codice (gridRender è la griglia a cui vengono aggiunti i controlli):

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

Nota: la classe VisualTreeHelperUtil è la mia classe che aggiunge alcune utili funzionalità di ricerca alla classe VisualTreeHelper.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top