亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

WPF DataGrid - 如何在驗證錯誤后取消編輯行?

WPF DataGrid - 如何在驗證錯誤后取消編輯行?

C#
智慧大石 2023-07-22 18:30:04
我想在用戶單擊 ? 按鈕時取消連續更改。源代碼private void CancelChangesButton_Click(object sender, RoutedEventArgs e){? ? datagrid.CancelEdit();}CancelEdit() 效果很好,直到...我的 DateConverter 無法轉換回字符串。當 ViewModel 的屬性設置器拋出異常時,也會發生相同的行為。我在 DataGrid 中無能為力。唯一的方法是當光標位于紅色單元格中時按 ESC 鍵。我嘗試其他事情:datagrid.CancelEdit(DataGridEditingUnit.Row);datagrid.CancelEdit(DataGridEditingUnit.Cell);datagrid.CommitEdit();datagrid.IsReadOnly = true;// Add new item什么都沒發生。所以我開始挖掘 .NET Framework 源代碼,我發現了這一點:public class DataGrid : MultiSelector...? ? public bool CancelEdit(DataGridEditingUnit editingUnit)? ? {? ? ? ? return EndEdit(CancelEditCommand, CurrentCellContainer, editingUnit, true);? ? }-> .NET 參考源這里最重要的是 CurrentCellContainer,它從 CurrentCell 獲取值。接下來,我發現CurrentCell正在跟隨焦點。當我單擊 ? 按鈕時,CurrentCell 更改為操作列中的單元格,當我單擊 DataGrid 外部時,CurrentCell 更改為 null。因此,我必須將 CurrentCell 更改為帶有驗證錯誤的單元格,然后調用 CancelEdit()。我想的對嗎?如何查找所有存在驗證錯誤的單元格?還有其他方法可以取消編輯嗎?
查看完整描述

2 回答

?
人到中年有點甜

TA貢獻1895條經驗 獲得超7個贊

我意識到我不需要找到存在驗證錯誤的單元格。我需要做的就是在所有單元格上調用 CancelEdit() 。


private void CancelChangesButton_Click(object sender, RoutedEventArgs e)

{

    var cc = dataGrid.CurrentCell;

    foreach (var col in datagrid.Columns)

    {

        datagrid.CurrentCell = new DataGridCellInfo(datagrid.CurrentItem, col);

        datagrid.CancelEdit();

    }

    dataGrid.CurrentCell = cc;

}

它還可以與 DataGridTemplateColumn 一起使用。 解決方案代碼

但是,如果您想查找哪些單元格包含驗證錯誤,則需要更深入地研究。感謝@BionicCode,我找到了解決方案。


可以得到可視化的DataGridRow:


DataGridRow row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(item);

然后你就可以檢查錯誤:


if (Validation.GetHasError(row))

并且您還可以訪問row.BindingGroup,其中包含該行中的所有綁定 (.BindingExpressions) 以及許多其他信息(IsDirty、ValidationErrors、ValidationRules、CancelEdit())


但是,當您想要檢查單元格中的錯誤時,事情就沒那么容易了。不幸的是,DataGridCell 不包含有關錯誤的信息,Validation.GetHasError(cell)無法正常工作。您需要更深入地研究視覺樹。


private void CancelChangesCellsHavingError()

{

    SomethingItem item = datagrid.CurrentItem as SomethingItem;


    DataGridRow row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(item);


    if (Validation.GetHasError(row))

    {

        var cc = dataGrid.CurrentCell;

        foreach (DataGridColumn col in datagrid.Columns)

        {

            DataGridCell cell = (DataGridCell)col.GetCellContent(item).Parent;

            List<DependencyObject> errs = GetVisualChildrenHavingError(cell);

            if (errs != null)

            {

                datagrid.CurrentCell = new DataGridCellInfo(item, col);

                datagrid.CancelEdit(DataGridEditingUnit.Cell);

            }

        }

        dataGrid.CurrentCell = cc;

    }

}


/// <summary>

/// Returns all visual children that HasError. Return null if nothing is found.

/// </summary>

public static List<DependencyObject> GetVisualChildrenHavingError(DependencyObject parent)

{

    List<DependencyObject> result = null;

    GetVisualChildrenHavingError(parent, ref result);

    return result;

}


private static void GetVisualChildrenHavingError(DependencyObject parent, ref List<DependencyObject> result)

{

    for (int childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(parent); childIndex++)

    {

        DependencyObject childElement = VisualTreeHelper.GetChild(parent, childIndex);


        if (Validation.GetHasError(childElement))

        {

            if (result == null)

                result = new List<DependencyObject>();


            result.Add(childElement);

        }


        GetVisualChildrenHavingError(childElement, ref result);

    }

}

有用的鏈接 - 綁定、驗證、DataGrid:


查看完整回答
反對 回復 2023-07-22
?
慕斯王

TA貢獻1864條經驗 獲得超2個贊

紅細胞顯示驗證錯誤。只要存在驗證錯誤,您就無法取消編輯模式(除非用戶按Escape鍵)。

唯一的解決方案是通過簡單地恢復輸入來手動解決錯誤。

算法如下:

  1. 獲取當前單元格

  2. 獲取當前cell的容器

  3. 檢查容器(單元)是否存在驗證錯誤。如果是,則繼續步驟 4,否則只需取消編輯(跳至步驟 9)

  4. TextBox獲取單元格模板的編輯

  5. TextBox.Text識別編輯屬性的綁定源(數據項)屬性

  6. 獲取屬性的值(使用反射來實現通用行為)

  7. 恢復內容

  8. 將鍵盤焦點移回編輯TextBox,這將觸發重新驗證并定義取消的目標單元格。

  9. 取消編輯

執行:

private void CancelChangesButton_Click(object sender, RoutedEventArgs e)

{

  DependencyObject cellItemContainer = this.datagrid.ItemContainerGenerator.ContainerFromItem(

    (this.datagrid.CurrentCell.Item as SomethingItem));


  // If the current cell has validation errors find the edit TextBox child control

  if (Validation.GetHasError(cellItemContainer) && TryFindChildElement(cellItemContainer, out TextBox editTextBox))

  {

    // Get the property name of he binding source

    var propertyName = (editTextBox.BindingGroup.BindingExpressions.FirstOrDefault() as BindingExpression)?.ResolvedSourcePropertyName ?? string.Empty;


    // Use reflection to get the value of the binding source

    object value = this.datagrid.CurrentCell.Item.GetType().GetProperty(propertyName).GetValue(this.datagrid.CurrentCell.Item);


    // Check which ToString() to invoke

    editTextBox.Text = value is DateTime date 

      ? date.ToShortDateString() 

      : value.ToString();


    // Trigger validation and define which cell to cancel the edit

    // This is required because the edit TexBox lost focus

    Keyboard.Focus(editTextBox);

  }


  this.datagrid.CancelEdit();

}


// Traverses the visual tree to find a child element of type TElement

private bool TryFindVisualChild<TChild>(DependencyObject parent, out TChild resultElement) where TChild : DependencyObject

{

  resultElement = null;

  for (var childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(parent); childIndex++)

  {

    DependencyObject childElement = VisualTreeHelper.GetChild(parent, childIndex);


    if (childElement is Popup popup)

    {

      childElement = popup.Child;

    }


    if (childElement is TChild)

    {

      resultElement = childElement as TChild;

      return true;

    }


    if (TryFindVisualChild(childElement, out resultElement))

    {

      return true;

    }

  }


  return false;

}


查看完整回答
反對 回復 2023-07-22
  • 2 回答
  • 0 關注
  • 311 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號