Datagrid Установить фокус на вновь добавленную строку - PullRequest
7 голосов
/ 22 июля 2010

У меня есть сетка данных, связанная с наблюдаемой коллекцией. Когда пользователь нажимает кнопку «Добавить», он добавляет новую строку, и я делаю это, добавляя новый элемент в наблюдаемую коллекцию.

Я не могу понять, как сделать новую добавленную строку с первой ячейкой в ​​фокусе, как если бы мы редактировали. Я использую шаблон MVVM.

Есть идеи или предложения?

Ответы [ 6 ]

2 голосов
/ 22 сентября 2017

Ответ, данный Гауссом , является правильным подходом, но с некоторым кодом он более ясен:

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

Вы извлекаете строку в событии DataGrid.LoadingRow, но ячейка еще не доступна. Таким образом, вы помещаете обработчик в событие Loaded, чтобы дождаться его возникновения, а затем можете извлечь ячейку и сфокусироваться на ней.

Обработчик удален, чтобы избежать нового запуска.

Сессия редактирования также может быть запущена с dataGrid.BeginEdit().

Все это в коде, потому что оно принадлежит представлению.

1 голос
/ 08 июня 2011

Попробуйте захватить событие DataGrid LoadingRow (или аналогичное).Сделайте SetFocus(e.Row) (или подобное) в строке.Это чисто View-ориентированный, поэтому он соответствует MVVM.

0 голосов
/ 22 января 2019

Решено в моем случае благодаря ответу Джейка Бергера.

Привязка SelectedItem объекта DataGrid и обработка события LoadingRow работает прекрасно.

например:.

<DataGrid SelectionUnit="FullRow" SelectionMode="Single" ItemsSource="{Binding Source=MyList}" SelectedItem="{Binding SelectedDataItem, Mode=TwoWay}" LoadingRow="MyDataGrid_LoadingRow"></DataGrid>
private void MyDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
          SelectedDataItem = (MyDataObject)e.Row.Item;
}
0 голосов
/ 08 октября 2015

Для меня работало сочетание LoadingRow, e.Row.Loaded и GetCell() метода по следующей ссылке:

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

Событие DataGrid.LoadingRowвызывается до того, как ячейка станет доступной через GetCell.Но в событии DaraGridRow.Loaded ячейка доступна.

После этого вы можете использовать cell.Focus() и DataGrid.BeginEdit().

0 голосов
/ 13 июня 2014


Надежды, которые помогут другим.
Я покажу путь MVVM, в представлении:

<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>

теперь в View-Model:
вам нужно установить SelectedIndex после: добавить, удалить и т.д ... и

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

кстати, чтобы выбрать первую строку после загрузки элемента управления, добавьте это в представление:

        <!-- 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> 

спасибо, Ави.

0 голосов
/ 24 октября 2011

Вы хотите сделать что-то вроде этого:

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

Конечно, вам нужен этот неуловимый метод GetCell ().Винсент Сибал из MSFT написал этот метод (и необходимый GetRow) в этом сообщении на форуме .Я искал что-то еще, когда натолкнулся на это, поэтому я не использовал это, но другим, кажется, повезло с этим.Вы заметите, что есть ссылки на его блог , которые также могут оказаться полезными для всего, что связано с DataGrid.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...