WPF GridView не обновляется при изменении наблюдаемой коллекции

У меня есть Telerik RadGridView, привязанный к ObservableCollection определенного типа. При обновлении значения определенного свойства в этом типе обновляется соответствующая коллекция Observable, но не RadGridView..

Ниже приведен XAML:

<ComboBox Grid.Column="4" Width="100" Margin="4" ItemsSource="{Binding Path=ResultUnits, Mode=OneTime}" SelectedValue="{Binding Path=ResultUnit}"/>

<telerik:RadGridView ItemsSource="{Binding Path=Results, Mode=TwoWay}" FooterRowStyle="{StaticResource GridViewFooterStyle}" Width="{Binding RelativeSource={RelativeSource AncestorType= ScrollViewer}, Path=ActualWidth}" ColumnWidth="*" RowIndicatorVisibility="Collapsed" EditTriggers="None" IsFilteringAllowed="False" AutoGenerateColumns="False" AllowDrop="False" CanUserFreezeColumns="False" CanUserReorderColumns="False" CanUserDeleteRows="False" CanUserInsertRows="False" ShowGroupPanel="False" ShowColumnFooters="True">
 <telerik:RadGridView.Columns>
  <telerik:GridViewDataColumn Header="Quantity" DataMemberBinding="{Binding Path=Quantity}"/>
  </telerik:RadGridView.Columns>
</telerik:RadGridView>

Ниже приведен код модели представления:

public class ViewModel {

    private const decimal PoundsToKilograms = 0.45359237M;

    private const decimal GramstoPound = 0.00220462262M;

    private ObservableCollection<Result> results;

    public EnvironmentalSummaryViewModel() {
        this.results= new ObservableCollection<Result>();
    }

    public ObservableCollection<Result> Results{
        get {
            return this.results;
        }

        set {
            this.results = value;
        }
    }

  public string ResultUnit {
        get {
            return this.resultUnit;
        }

        set {
            if (this.resultUnit != value) {
                this.resultUnit = value;
                this.UpdateGridViewValuesOnResultUnitChanged();
            }
        }
    }

   private void UpdateGridViewValuesOnResultUnitChanged() {
        bool isEnglish = this.resultUnit == this.resultUnits[0];
        this.results.ToList().ForEach(result => {
            decimal weight = isEnglish ? result.Weight * GramstoPound * 1000 : environmental.Weight * PoundsToKilograms;
            result.Weight = Math.Round(weight, 2);
        });

        ((IHaveOnPropertyChangedMethod) this).OnPropertyChanged("Results");
    }
}

Класс объекта:

public class Result{
   public decimal Weight { get; set; }
}

person Arihant    schedule 19.02.2011    source источник


Ответы (3)


Каждый элемент в наблюдаемой коллекции должен иметь способ сообщить WPF и, следовательно, элементу управления, который он обновляет, чтобы можно было обновить значение количества. Обновление Observable Collection происходит, потому что эта коллекция содержит встроенное уведомление об изменении для своей коллекции, но не для отдельных ее элементов. Как уже говорили другие, реализуйте INotifyPropertyChanged в результате, и он должен работать.

public class Result : INotifyPropertyChanged
{

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected void Notify(string propName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
    #endregion


    private decimal _weight;

    public decimal Weight
    {
        get { return _weight; }
        set { 

            this._weight = value;
            Notify("Weight");
        }
    }
}
person Andrew    schedule 19.02.2011

Как сказал Эрно, ваш класс Result должен реализовать INotifyPropertyChanged, и вам нужно вызвать OnPropertyChanged для свойства Weight.

Кроме того, ваша ViewModel также должна реализовывать INotifyPropertyChanged, чтобы вы могли избежать приведения к IHaveOnPropertyChangedMethod (кстати, это довольно плохое имя), которое у вас есть в вашем коде. Я бы предложил иметь класс ViewModelBase : INotifyPropertyChanged, от которого наследуются все ваши ViewModels. Если вы не хотите писать его самостоятельно, существует множество фреймворков MVVM, в которые это встроено.

person alimbada    schedule 19.02.2011
comment
Пробовал это.((IHaveOnPropertyChangedMethod) это).OnPropertyChanged(Weight); - person Arihant; 19.02.2011

Если выполняемое вами обновление является обновлением свойства Weight объекта Result, это может быть вызвано тем, что класс Result не реализует INotifyPropertyChanged.

ICollectionChanged (и, следовательно, ObservableCollection тоже) уведомляет только об изменениях в коллекции (добавление и удаление элементов).

person Emond Erno    schedule 19.02.2011
comment
это.((IHaveOnPropertyChangedMethod) это).OnPropertyChanged(Weight); не будет работать, потому что модель представления не реализует INotifyPropertyChanged. - person Emond Erno; 19.02.2011