none
Simular tecla Down por codigo WPF C# RRS feed

  • Pregunta

  • Buenas noches:

    Tengo un Listview que cuando le doy Listview.Focus() tengo que pulsar la tecla Down para que el foco se ponga el la primera fila.

    Para evitar que el usuario tenga que hacer esto, cómo puedo simular "presionar la tecla Down" para que el foco aparezca directamente en la primera fila?

    Gracias

    lunes, 20 de octubre de 2014 0:22

Respuestas

  • En ese caso podrías hacer esto:

     private void LvwSecciones_Loaded(object sender, RoutedEventArgs e)
    {
        LvwSecciones.ItemsSource = oSeccion.Listar();
    
        Dispatcher.BeginInvoke(new Action(() => 
          { 
              LvwSecciones.Focus();
    
              int index = 0;
              LvwSecciones.SelectedIndex = index;
    
              var item = LvwSecciones.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;
              if (item != null)
              {
                  item.Focus();
              }
          }));    
    }

    En este caso intentará colocar el foco y seleccionar el elemento de manera asincrónica.

    Espero que sea lo que buscas.

    Saludos


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile

    • Marcado como respuesta MarioSharp lunes, 20 de octubre de 2014 19:01
    lunes, 20 de octubre de 2014 18:38

Todas las respuestas

  • Hola Mario, la parte del ListView.Focus() ya lo tiene en el constructor o en el evento Loaded de tu Ventana o Control de Usuario. Ahora, dentro del evento KeyUp del LsitView puedes hacer algo así:

    private void listView1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Down)
        {
            //Verificamos si no hay elementos seleccionados, sino lo hay se selecciona el primer elemento.
            if (this.listView1.SelectedIndex < 0)
                this.listView1.SelectedIndex = 0;
        }
    }

    Espero resulte útil.

    Saludos.


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile

    lunes, 20 de octubre de 2014 13:32
  • Hola Christian:
    Sigue igual.
    Al parecer el método que me has enviado es cuando el usuario presiona la tecla Down mas no para que se presione "sola", que es lo que necesito para que el foco se coloque en la primera fila del Listview.
    El código que tengo, con lo que me has enviado, es:
           private void LvwSecciones_Loaded(object sender, RoutedEventArgs e)
            {
                LvwSecciones.ItemsSource = oSeccion.Listar();

                //LvwSecciones.SelectedIndex = 2;
                LvwSecciones.Focus();

                int index = 0;
                LvwSecciones.SelectedIndex = index;

                var item = LvwSecciones.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;
                if (item != null)
                {
                    item.Focus();
                }
            }

            private void LvwSecciones_KeyUp(object sender, KeyEventArgs e)
            {
                if (e.Key == Key.Down)
                {
                    //Verificamos si no hay elementos seleccionados, sino lo hay se selecciona el primer elemento.
                    if (this.LvwSecciones.SelectedIndex < 0)
                        this.LvwSecciones.SelectedIndex = 0;
                }
            }
    Pero igual tengo que presionar la tecla Down manualmente....
    Gracias
    Saludos

    Mario Escudero www.cheff2000.com Lima, Perú

    lunes, 20 de octubre de 2014 18:24
  • En ese caso podrías hacer esto:

     private void LvwSecciones_Loaded(object sender, RoutedEventArgs e)
    {
        LvwSecciones.ItemsSource = oSeccion.Listar();
    
        Dispatcher.BeginInvoke(new Action(() => 
          { 
              LvwSecciones.Focus();
    
              int index = 0;
              LvwSecciones.SelectedIndex = index;
    
              var item = LvwSecciones.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;
              if (item != null)
              {
                  item.Focus();
              }
          }));    
    }

    En este caso intentará colocar el foco y seleccionar el elemento de manera asincrónica.

    Espero que sea lo que buscas.

    Saludos


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile

    • Marcado como respuesta MarioSharp lunes, 20 de octubre de 2014 19:01
    lunes, 20 de octubre de 2014 18:38
  • Excelente Christian !!!

    Eso era exactamente lo que necesitaba. 

    Voy a probarlo también con un Datagrid. Supongo que funcionará igual. Te cuento...

    A qué te refieres con:

    En este caso intentará colocar el foco y seleccionar el elemento de manera asincrónica?

    Gracias nuevamente


    Mario Escudero www.cheff2000.com Lima, Perú

    lunes, 20 de octubre de 2014 19:03
  • Hola Christian.

    Efectivamente, como lo pensé, funciona igual para el Datagrid.

    Te paso el código por si acaso....

            private void dgSecciones_Loaded(object sender, RoutedEventArgs e)
            {
                dgSecciones.ItemsSource = oSeccion.Listar();
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    dgSecciones.Focus();

                    SelectRowByIndex(dgSecciones, 2);
                }));
            }

    El método SelectRowByIndex(dgSecciones, 2) se relaciona con otros dos métodos más que los copio abajo. Saludos

    Con este método sólo "pintaba" la fila pero no caía el foco, lo cual sí he podido lograr con lo que me mandaste.

    Ahí van....

            public static void SelectRowByIndex(DataGrid dgSecciones, int rowIndex)
            {
                if (!dgSecciones.SelectionUnit.Equals(DataGridSelectionUnit.FullRow))
                    throw new ArgumentException("The SelectionUnit of the DataGrid must be set to FullRow.");

                if (rowIndex < 0 || rowIndex > (dgSecciones.Items.Count - 1))
                    throw new ArgumentException(string.Format("{0} is an invalid row index.", rowIndex));

                dgSecciones.SelectedItems.Clear();
                /* set the SelectedItem property */
                object item = dgSecciones.Items[rowIndex]; // = Product X
                dgSecciones.SelectedItem = item;

                DataGridRow row = dgSecciones.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
                if (row != null)
                {
                    DataGridCell cell = GetCell(dgSecciones, row, 0);
                    if (cell != null)
                        cell.Focus();
                }
                //TODO: Retrieve and focus a DataGridCell object
            }

           
            public static DataGridCell GetCell(DataGrid dgSecciones, DataGridRow rowContainer, int column)
            {
                if (rowContainer != null)
                {
                    DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
                    if (presenter == null)
                    {
                        /* if the row has been virtualized away, call its ApplyTemplate() method 
                         * to build its visual tree in order for the DataGridCellsPresenter
                         * and the DataGridCells to be created */
                        rowContainer.ApplyTemplate();
                        presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
                    }
                    if (presenter != null)
                    {
                        DataGridCell cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
                        if (cell == null)
                        {
                            /* bring the column into view
                             * in case it has been virtualized away */
                            dgSecciones.ScrollIntoView(rowContainer, dgSecciones.Columns[column]);
                            cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
                        }
                        return cell;
                    }
                }
                return null;
            }

            public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                    if (child != null && child is T)
                        return (T)child;
                    else
                    {
                        T childOfChild = FindVisualChild<T>(child);
                        if (childOfChild != null)
                            return childOfChild;
                    }
                }
                return null;
            }


    Mario Escudero www.cheff2000.com Lima, Perú

    lunes, 20 de octubre de 2014 19:19
  • Mario, me refería al Dispatcher.BeginInvoke... :)

    Saludos.


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile

    lunes, 20 de octubre de 2014 20:09
  • Excelente. Gracias Mario.

    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile

    lunes, 20 de octubre de 2014 20:09
  • Ah ok. Lo que pasa es que recién estoy viendo WPF....

    Te cuento luego cómo me va yendo.

    Saludos


    Mario Escudero www.cheff2000.com Lima, Perú

    lunes, 20 de octubre de 2014 20:30