簡體   English   中英

如何將單元格聚焦在 WPF DataGrid 中的新行上

[英]How to focus cell on new row in WPF DataGrid

.Net 4 WPF DataGrid MVVM

用戶單擊添加按鈕觸發視圖模型上的命令。 在 viewmodel 命令執行中,我將一個新對象添加到網格綁定到的視圖模型的視圖集合中。 新行確實出現在我的網格中。 但是,我還想將焦點發送到該新行中的第一個可編輯單元格。

我什至“欺騙”了 mvvm,在我的視圖模型上添加了一個視圖監聽的事件,以了解何時關注新行。

我已經搜索過,但沒有運氣。 當我遇到這個時,我充滿希望:

Datagrid 將焦點設置在新添加的行上

這導致

http://social.msdn.microsoft.com/forums/en-US/wpf/thread/63974f4f-d9ee-45af-8499-42f29cbc22ae

但是其他人反映的問題卻沒有人回答,就是如何處理網格的虛擬化行為。 新添加的行尚未創建。 因此 GetCells 調用經常失敗。 如果需要 ScrollIntoView,則失敗的可能性更大。

我已經吸引了大量事件,包括 LoadingRow 和 RequestBringIntoView ,但沒有運氣。 根據我掛鈎的事件,我設法能夠獲得對單元格的引用。 但是后來我收到錯誤消息“在生成內容時無法調用 StartAt”。 但是我檢查了 ItemContainerGenerator 的狀態,當我調用單元格的 BeginEdit 時它是 ContainersGenerated。

這是以編程方式將焦點設置到特定單元格的一種方法:

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

有關 GetCell() 的更多信息,請參閱以下文章

這似乎對我有用:

    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    using System.Windows.Media;

    private void SetFocusOnNewRow(DataGrid theDataGrid, Int32 columnIndex)
    {
        theDataGrid.UnselectAll();
        theDataGrid.UpdateLayout();

        Int32 newRowIndex = theDataGrid.Items.Count - 1;
        theDataGrid.ScrollIntoView(theDataGrid.Items[newRowIndex]);
        DataGridRow newDataGridRow = theDataGrid.ItemContainerGenerator.ContainerFromIndex(newRowIndex) as DataGridRow;

        DataGridCellsPresenter newDataGridCellsPresenter = GetVisualChild<DataGridCellsPresenter>(newDataGridRow);
        if (newDataGridCellsPresenter != null)
        {
            DataGridCell newDataGridCell = newDataGridCellsPresenter.ItemContainerGenerator.ContainerFromIndex(columnIndex) as DataGridCell;
            if (newDataGridCell != null)
                newDataGridCell.Focus();
        }
    }

    static T GetVisualChild<T>(Visual parent) where T : Visual
    {
        T child = default(T);
        int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < numVisuals; i++)
        {
            Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
            child = v as T;
            if (child == null)
            {
                child = GetVisualChild<T>(v);
            }
            if (child != null)
            {
                break;
            }
        }
        return child;
    }

這對我來說是工作:

private void button_Click(object sender, RoutedEventArgs e)
{
    //Scroll to the last row
    var border = VisualTreeHelper.GetChild(dataGrid, 0) as Decorator;
    if (border != null)
    {
        var scroll = border.Child as ScrollViewer;
        if (scroll != null) scroll.ScrollToEnd();
    }

    //Edit the first cell of the last row
    int lastRow = dataGrid.Items.Count - 1;
    DataGridCell cell = GetCell(lastRow, 0);
    cell.Focus();
    dataGrid.BeginEdit();
}


public DataGridCell GetCell(int row, int column)
{
    DataGridRow rowContainer = GetRow(row);

    if (rowContainer != null)
    {
        DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);

        // try to get the cell but it may possibly be virtualized
        DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
        if (cell == null)
        {
            // now try to bring into view and retreive the cell
            dataGrid.ScrollIntoView(rowContainer, dataGrid.Columns[column]);
            cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
        }
        return cell;
    }
    return null;
}

public DataGridRow GetRow(int index)
{
    DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(index);
    if (row == null)
    {
        // may be virtualized, bring into view and try again
        dataGrid.ScrollIntoView(dataGrid.Items[index]);
        row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(index);
    }
    return row;
}

static T GetVisualChild<T>(Visual parent) where T : Visual
{
    T child = default(T);
    int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < numVisuals; i++)
    {
        Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
        child = v as T;
        if (child == null)
        {
            child = GetVisualChild<T>(v);
        }
        if (child != null)
        {
            break;
        }
    }
    return child;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM