![](/img/trans.png)
[英]DataGrid CellEditEnding event not firing on a cell editing inside DataGridTemplateColumn
[英]Modifying DataGrid cell values on CellEditEnding event
我一直在嘗試在WPF DataGrid控件的CellEditEnding事件處理程序內的同一行中更改其他單元格值。
如果我在現有行中編輯單元格值,它將按預期工作。 但是,在添加新行時,如果在不進入編輯模式的情況下用鼠標單擊了另一個單元格值,則更改不會反映到UI。
通過按Tab鍵將焦點移到下一個單元格也可以按預期方式工作,但是單擊也不能正常工作嗎?
public MainWindow()
{
InitializeComponent();
DataTable dataTable = new DataTable();
dataTable.Columns.Add(new DataColumn());
dataTable.Columns.Add(new DataColumn());
DataRow existingRow = dataTable.NewRow();
dataTable.Rows.Add(existingRow);
this.MyDataGrid.ItemsSource = dataTable.DefaultView;
this.MyDataGrid.CellEditEnding += MyDataGrid_CellEditEnding;
}
void MyDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
(e.Row.Item as DataRowView).Row[1] = "a string that should be displayed immediatly";
}
到目前為止,我已經嘗試更改綁定UpdateSourceTrigger,NotifyOnSourceUpdated和NotifyOnTargetUpdated,但是似乎沒有任何效果。 我還嘗試通過閱讀相關主題來進行修正: http : //codefluff.blogspot.fi/2010/05/commiting-bound-cell-changes.html
但是這些似乎也沒有幫助。
我發現可以正常工作的一種方式是以下代碼段:
var frameworkElement = this.MyDataGrid.Columns[1].GetCellContent(e.Row);
frameworkElement.SetValue(TextBlock.TextProperty, "a string that should be displayed immediatly");
但是我不想依賴於dependencyproperties,因為我可能不知道底層的顯示類型。
所以問題是,在不使用提供的第二代碼段的情況下,如何在新行中實現UI更新,因為它可以與現有行一起工作? 我覺得我想念一些東西。
編輯:使用ClipboardPaste也可以用於設置新值,但是由於某些原因,原始的編輯值將丟失。
Edit2:xaml當前是普通的DataGrid,我嘗試手動處理列及其綁定,但是由於我沒有使其工作,因此我刪除了它們以使示例代碼保持簡單
<DataGrid x:Name="MyDataGrid" />
Edit3:添加了此圖像以更好地描述問題。 因此,在單擊下一個單元格后,我希望顯示文本。問題的示例圖像
Edit4:使用snoop查看單元格似乎將元素設置為可見,同時調用.UpdateTarget();。 因為綁定似乎有幫助,但是它不能自動運行。 仍然想知道是什么原因。
Edit5:我希望它可以與DataTable一起使用,因為我需要其他功能
測試了大量不同類型的解決方案后,我最終在開始編輯單元格時添加了該行。 由於我要尋找的功能正在現有行中使用,因此確實解決了該問題。
public class MyDataGrid : DataGrid
{
protected override void OnBeginningEdit(DataGridBeginningEditEventArgs e)
{
base.OnBeginningEdit(e);
this.CommitEdit();
}
protected override void OnCellEditEnding(DataGridCellEditEndingEventArgs e)
{
base.OnCellEditEnding(e);
(e.Row.Item as DataRowView).Row[1] = "a string that should be displayed immediatly";
}
}
我建議您使用MVVM方式,然后通過WPF本身的內置通知機制滿足您的要求,其中在數據上下文中某些屬性更新時,您可以觸發另一個屬性的更新。 示例:1. Xaml代碼:
<Window x:Class="DataGridSoHelpAttempt.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dataGridSoHelpAttempt="clr-namespace:DataGridSoHelpAttempt"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<dataGridSoHelpAttempt:MainViewModel/>
</Window.DataContext>
<Grid>
<DataGrid x:Name="MyDataGrid" ItemsSource="{Binding DataSource}"/>
</Grid></Window>
2.查看模型代碼:
public class MainViewModel:BaseObservableObject
{
public MainViewModel()
{
DataSource = new ObservableCollection<BaseData>(new List<BaseData>
{
new BaseData {Name = "John"},
new BaseData {Name = "Ron"},
new BaseData {Name = "Bob"},
});
}
public ObservableCollection<BaseData> DataSource { get; set; }
}
3.型號代碼:
public class BaseData:BaseObservableObject
{
private string _name;
private string _description;
public virtual string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
Description = "a string that should be displayed immediatly";
}
}
public virtual object Description
{
get { return _description; }
set
{
_description = (string) value;
OnPropertyChanged();
}
}
}
4. BaseObservableObject一個基本的INotifyPropertyChanged實現:
public class BaseObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> raiser)
{
var propName = ((MemberExpression)raiser.Body).Member.Name;
OnPropertyChanged(propName);
}
protected bool Set<T>(ref T field, T value, [CallerMemberName] string name = null)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
OnPropertyChanged(name);
return true;
}
return false;
}
}
5.請記住,模型的屬性對象可能很復雜(例如描述另一個視圖模型的圖像或類),但是在這種情況下,您必須對數據網格列或單元格進行模板化(示例鏈接: WPF DataGrid Control )。
如果您遇到代碼方面的問題,我將非常樂意提供幫助。 問候
更新 1.后面的代碼-您應該更新DataTable,但是請考慮到必須對Table中已經存在的行執行更新:
public partial class MainWindow : Window
{
private readonly DataTable _dataTable;
public MainWindow()
{
InitializeComponent();
this.MyDataGrid.CellEditEnding += MyDataGrid_CellEditEnding;
_dataTable = new DataTable();
_dataTable.Columns.Add(new DataColumn());
_dataTable.Columns.Add(new DataColumn());
DataRow existingRow = _dataTable.NewRow();
_dataTable.Rows.Add(existingRow);
this.MyDataGrid.ItemsSource = _dataTable.DefaultView;
}
void MyDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
var dataRowView = (e.Row.Item as DataRowView);
var columnIndex = e.Column.DisplayIndex;
var rowIndex = e.Row.GetIndex();
var dv = _dataTable.DefaultView;
var nextColumnIndex = columnIndex + 1;
if (dv.Table.Columns.Count <= nextColumnIndex || dv.Table.Rows.Count <= rowIndex) return;
dv.Table.Rows[rowIndex][nextColumnIndex] = "a string that should be displayed immediatly";
}
}
2. Xaml:
<Window x:Class="GridViewWitaFDataTableSoHelpAttempt.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="MyDataGrid" />
</Grid></Window>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.