2010-07-22 11 views
6

Tengo una cuadrícula de datos vinculada a una colección observable. Cuando el usuario presiona el botón "agregar" agrega una nueva fila y hago esto agregando un nuevo elemento a la colección observable.Cuadrícula de datos Establecer foco en la fila recién agregada

No puedo imaginar cómo hacer que la fila recién agregada con la primera celda en foco como si estuviéramos editando. Estoy usando un patrón MVVM.

¿Alguna idea o sugerencia?

Respuesta

0

Intente capturar el evento LoadingRow de DataGrid (o similar). Haga un SetFocus(e.Row) (o similar) en la fila. Esto está orientado exclusivamente a la vista, por lo que se ajusta a MVVM.

0

que quiere hacer algo como esto:

DataGridCell cell = GetCell(rowIndex, colIndex); 
cell.Focus; 

Por supuesto que necesita método que esquiva GetCell(). Vincent Sibal de MSFT escribió ese método (y el GetRow requerido también) en this forum post. Estaba buscando algo más cuando me encontré con esto, así que no lo he usado, pero otros parecen haber tenido buena suerte con él. Notarás que hay enlaces a his blog que también pueden ser útiles para todo lo relacionado con DataGrid.

0


Esperanzas que ayudarán a los demás.
Voy a mostrar la forma en MVVM, en la vista:

<DataGrid Name="dg1" ItemsSource="{Binding Table}" AutoGenerateColumns="False" Margin="3" SelectionMode="Single" IsReadOnly="True" SelectedIndex="{Binding Path=SelectedIndex, Mode=TwoWay}"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Date" Binding="{Binding mydate}" MinWidth="100"></DataGridTextColumn> 
     <DataGridTextColumn Header="Count" Binding="{Binding Count}" MinWidth="100"></DataGridTextColumn> 
    </DataGrid.Columns> 

    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="SelectionChanged" SourceName="dg1" > 
      <i:InvokeCommandAction Command="{Binding DgSelectionChanged}" CommandParameter="{Binding ElementName=dg1}"/> 
     </i:EventTrigger> 

    </i:Interaction.Triggers>   
</DataGrid> 

ahora en la Vista-Modelo:
debe configurar el SelectedIndex después de: añadir, eliminar, etc ... y

private ICommand dgSelectionChanged; 
    /// <summary> 
    /// when the datagrid Selection Changes 
    /// </summary> 
    public ICommand DgSelectionChanged 
    { 
     get 
     { 
      return dgSelectionChanged ?? 
      (dgSelectionChanged = new RelayCommand<DataGrid>(dg1 => 
      { 
       // whatever you want when the Selection Changes 


       SelectedIndex= d 
       //select the item 
       if (dg1.SelectedIndex > -1) 
       { 
        dg1.Focus(); 
        dg1.CurrentCell = new DataGridCellInfo(dg1.Items[dg1.SelectedIndex], dg1.Columns[0]); 
       } 
      })); 
     } 
    } 

por cierto, para seleccionar la primera fila después del control de carga, añadir esto a la vista:

 <!-- select the row after control loaded --> 
     <i:EventTrigger EventName="Loaded" SourceName="dg1" > 
      <i:InvokeCommandAction Command="{Binding DgSelectionChanged}" CommandParameter="{Binding ElementName=dg1}"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 

gracias, Avi.

0

lo que funcionó para mí fue una combinación del LoadingRow, e.Row.Loaded y del método del siguiente enlace GetCell():

http://social.technet.microsoft.com/wiki/contents/articles/21202.wpf-programmatically-selecting-and-focusing-a-row-or-cell-in-a-datagrid.aspx

El evento se llama antes de DataGrid.LoadingRow la célula está disponible través de GetCell. Pero en el evento DaraGridRow.Loaded, la celda está disponible.

Después de eso, puede usar cell.Focus() y DataGrid.BeginEdit().

0

The answer given by Gauss es el enfoque correcto, pero con algo de código, es más claro:

void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e) 
{ 
    e.Row.Loaded += Row_Loaded; 
} 

void Row_Loaded(object sender, RoutedEventArgs e) 
{   
    var row = (DataGridRow) sender; 
    row.Loaded -= Row_Loaded; 
    DataGridCell cell = GetCell(dataGrid, row, 0); 
    if (cell != null) cell.Focus(); 
    dataGrid.BeginEdit();   
} 

static DataGridCell GetCell(DataGrid dataGrid, DataGridRow row, int column) 
{ 
    if (dataGrid == null) throw new ArgumentNullException("dataGrid"); 
    if (row == null) throw new ArgumentNullException("row"); 
    if (column < 0) throw new ArgumentOutOfRangeException("column"); 

    DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(row); 
    if (presenter == null) 
    { 
     row.ApplyTemplate(); 
     presenter = FindVisualChild<DataGridCellsPresenter>(row); 
    } 
    if (presenter != null) 
    { 
     var cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell; 
     if (cell == null) 
     { 
      dataGrid.ScrollIntoView(row, dataGrid.Columns[column]); 
      cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell; 
     } 
     return cell; 
    } 
    return null; 
} 

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

Usted recuperar la fila en caso DataGrid.LoadingRow, pero la célula no está disponible todavía. Así que pones un controlador en el evento Loaded para esperar a que ocurra este evento y luego puedes recuperar la celda y enfocarte en ella.

Se quitó el controlador para evitar un nuevo disparo.

La sesión de edición también se puede iniciar con dataGrid.BeginEdit().

Todo esto está en el código subyacente, porque pertenece a la vista.

Cuestiones relacionadas