DataGrid только обновляет выбранную ячейку - PullRequest
0 голосов
/ 03 октября 2011

Таким образом, я попал в проблему. Я могу обновить значения в сетке данных, когда текстовое поле редактирует значение ячейки, в которой выбрана сетка данных, это приводит к мгновенному обновлению пользовательского интерфейса.Питфал в том, что я не могу обновить произвольные ячейки, которые зависят от значения этой ячейки.Данные, в которых ячейка / столбец привязаны к изменениям, все же 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 необходимых ячеек модели для привязки, чтобы не генерировать миллион исключений нулевого указателя.

1 Ответ

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

Я думаю, что проблема в вашей части столбцов на основе индекса indexAbleArr[" + i + "] в пути привязки ваших DataGridTextColumns.Они не участвуют в уведомлениях об изменении свойства.

Как BalamBalam предложил сделать этот массив в ObservableCollection, или вы должны повышать уведомление об изменении свойства на уровне строки для свойства "indexAbleArr", когда любая ячейка внутри этого массиваизменяет это Value.

И то, и другое для меня на самом деле неполные проекты.(

...