Таким образом, я попал в проблему. Я могу обновить значения в сетке данных, когда текстовое поле редактирует значение ячейки, в которой выбрана сетка данных, это приводит к мгновенному обновлению пользовательского интерфейса.Питфал в том, что я не могу обновить произвольные ячейки, которые зависят от значения этой ячейки.Данные, в которых ячейка / столбец привязаны к изменениям, все же DataGrid не обновляет значения зависимых ячеек.У меня много ячеек, поэтому вызывать DataGrid.Item.Refresh () очень дорого.Я попытался создать метод, который просто вызывает измененное событие InotifyProperty, но это не вызывает обновления в сетке.Я в недоумении, как заставить графический интерфейс для обновления.
Код для ячейки модели ниже.и код привязки находится под ним.
public class ModelCell : INotifyPropertyChanged {
//This is a class that represents a cell that a user clicks on. it contains few items. And should have a reference to the SpreadSheet object
public String CellName {
get;
set;
}
public IEnumerable<String> dependents {
get;
private set;
}
public String Contents {
get {
return Host.GetCellContents(CellName);
}
set {
if (value != _contents) {
IEnumerable<String> tmpDep = Host.SetCellContents(CellName, value);
try {
if (Host.GetCellValue(CellName) is SS.FormulaError) {
//Revert the change.
Host.SetCellContents(CellName, _contents);
} else {
_contents = value;
NotifyPropertyChanged("Contents");
NotifyPropertyChanged("Value");
//Next is to notify dependents that we have changed. Since the names will be in the Format of A1
this.dependents = tmpDep;
}
} catch (Exception e) {
//We got an exception no change was made to the sheet anyway.
MessageBox.Show(e.Message);
}
} else NotifyPropertyChanged("Value");
}
}
public int Row;
public int Col;
public override string ToString () {
return "THis is a test!";
}
/// <summary>
/// Default initialize the empty cell to empty contents. this makes the construction of the objects simpler;
/// </summary>
private String _contents = "";
/// <summary>
/// This value is contained in the SpreadSheet so it is automatically changed with the Contents.
/// </summary>
public String Value {
get {
try {
Object returned = Host.GetCellValue(CellName);
if (returned is String || returned is Double)
return returned.ToString();
return ((SS.FormulaError)returned).Reason;
} catch (Exception e) {
MessageBox.Show("Cell " + this.CellName + " encountered an exception getting the value: " + e.Message);
return "";
}
}
set {
//instead assign contents
NotifyPropertyChanged("Value");
}
}
public SS.Spreadsheet Host {
set;
private get;
}
/// <summary>
/// Creates an empty cell with no value or contents with the specified name.
/// </summary>
/// <param name="Name">The Name of this cell generally in the format [A-Z][1-99]</param>
public ModelCell (String Name) {
this.CellName = Name;
}
public ModelCell () {
//Name will equal the base.ToString()
this.CellName = base.ToString();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged (String propertyName) {
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public MainWindow () {
InitializeComponent();
ViewModel = new MainViewModel();
DataGrid Sheet = null;
if (this.FindName("Sheet") is DataGrid)
Sheet = (DataGrid)this.FindName("Sheet");
if (Sheet == null)//Exit
this.Close();
IValueConverter converter = new ModelCellConverter();
Binding bind;
for (int i = 0; i < 26; i++) {
DataGridColumn col = new DataGridTextColumn();
col.Header = (char)('A' + i);
col.IsReadOnly = true;
col.Width = new DataGridLength(60);
col.CanUserSort = false;
//bind = new Binding(new String((char)('A' + i), 1));
bind = new Binding("indexAbleArr[" + i + "].Value");
//bind.Converter = new IdentityConverter();
bind.Mode = BindingMode.OneWay;
((DataGridTextColumn)col).Binding = bind;
Sheet.Columns.Add(col);
}
Sheet.ItemsSource = ViewModel.Rows;
//Current cell display
Label lab = null;
if (this.FindName("CurCell") is Label) {
lab = (Label)this.FindName("CurCell");
bind = new Binding("ActiveCell.CellName");
bind.Source = ViewModel;
bind.NotifyOnSourceUpdated = true;
lab.SetBinding(Label.ContentProperty, bind);
} //Don't bind the label if i cant find it
if (this.FindName("ValueBox") is Label) {
lab = (Label)this.FindName("ValueBox");
bind = new Binding("ActiveCell");
bind.Source = ViewModel;
bind.Converter = converter;
bind.NotifyOnSourceUpdated = true;
lab.SetBinding(Label.ContentProperty, bind);
}
TextBox content = null;
if (this.FindName("Content") is TextBox) {
content = (TextBox)this.FindName("Content");
bind = new Binding("ActiveCell.Contents");
bind.Source = ViewModel;
bind.Mode = BindingMode.TwoWay;
bind.NotifyOnSourceUpdated = true;
content.SetBinding(TextBox.TextProperty, bind);
}
ViewModel.ActiveCell = ViewModel.Rows[0].indexAbleArr[0];
}
Я использую XAML, чтобы указать макет, но через XAML не выполняется привязка, поэтому в моем коде XAML нет ничего примечательного.Rows - это Объект, который содержит массив ячеек модели (indexAbleArray) для целей связывания.Он также создает 26 необходимых ячеек модели для привязки, чтобы не генерировать миллион исключений нулевого указателя.