【问题标题】:Calculated DataGrid Column not updating, source is an entity计算的 DataGrid 列未更新,源是实体
【发布时间】:2014-11-05 07:26:37
【问题描述】:

这是对这个问题的跟进:

Entity Datagrid : best way to add computed values?

简而言之,我希望数据网格中的一列显示网格中其他两列的差异。我希望计算列的值在我在其他任一列中输入值时更新。

数据源是自动生成的实体。因此,在通过 ADO.NET 实体模型流程之后,访问数据库的顶级类是:

public partial class BenchMarkEntities : DbContext
    {
        public BenchMarkEntities()
            : base("name=BenchMarkEntities")
        {            }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

        public virtual DbSet<BenchmarkDescription> BenchmarkDescriptions { get; set; }
        public virtual DbSet<SecurityDescription> SecurityDescriptions { get; set; }
        public virtual DbSet<Weight> Weights { get; set; }

这是包含在 DbSet 集合中的示例类:

using System;
using System.Collections.ObjectModel;

public partial class Weight
{
    public int BenchmarkID { get; set; }
    public string Symbol { get; set; }
    public decimal Benchmark_Weight { get; set; }
    public decimal Security_Weight { get; set; }
    public string Symbol_and_BenchmarkID { get; set; }
    public bool Weight_Exists { get; set; }

    public virtual BenchmarkDescription BenchmarkDescription { get; set; }
    public virtual SecurityDescription SecurityDescription { get; set; }
}

在 MainWindow 中,我必须实例化一个 BenchmarkEntities 才能对数据库执行 CRUD 操作。下面的代码来自教程。如果你有更好的方法很想看看。

public partial class MainWindow : Window
{
    private BenchMarkEntities _context = new BenchMarkEntities();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        System.Windows.Data.CollectionViewSource weightViewSource =
          ((System.Windows.Data.CollectionViewSource)(this.FindResource("weightViewSource")));

        _context.Weights.Load();
        // Load data by setting the CollectionViewSource.Source property:
        weightViewSource.Source = _context.Weights.Local;

    }

因此,正如另一个问题所建议的那样,我在类中添加了一个属性(在这种情况下为重量)。当我运行它时,我得到一个正确的初始值。但是当我在其他列中输入值时,计算的列不会更新。

public partial class Weight : INotifyPropertyChanged
{
    public Weight()
    {
        this.PropertyChanged += ActiveWeightPropertyChanged;
    }

    void ActiveWeightPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case "Benchmark_Weight":
            case "Security_Weight":
                OnPropertyChanged("DiffValues");
                break;
        }
    }

    public decimal DiffValues
    {
        get
        {
            return Benchmark_Weight - Security_Weight;
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(
                this, new PropertyChangedEventArgs(propName));
    }

    #endregion

}

}

这是我的 XAML,第二个 DataGridTextColumn 绑定到我添加的附加属性。

  <DataGrid x:Name="weightDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" Margin="51,21,54,99" 
                  ItemsSource="{Binding}" EnableRowVirtualization="True" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="benchmark_WeightColumn" Width="SizeToHeader" 
                                    Header="Benchmark Weight" Binding="{Binding Benchmark_Weight}"/>
                <DataGridTextColumn x:Name="ActiveWeightColumn" Width="SizeToHeader" Header="ActiveWeight"
                                    Binding="{Binding DiffValues}"/>
                <DataGridTextColumn x:Name="security_WeightColumn" Width="SizeToHeader" Header="Security Weight" Binding="{Binding Security_Weight}"/>
                <DataGridTextColumn x:Name="symbolColumn" Width="SizeToHeader" Header="Symbol" Binding="{Binding Symbol}"/>
                <DataGridCheckBoxColumn x:Name="Weigh_ExistsColumn" Header="Remove" IsThreeState="False" Binding="{Binding Weight_Exists}"/>
            </DataGrid.Columns>
        </DataGrid>

我想我知道该怎么做,但不确定它是否可能。

  1. 我需要添加并实现 INotifyPropertyChanged 我相信 BenchMarkEntities 类?

  2. 然后我需要更改两个属性的设置器 通知 DiffValues。问题在于这些是自动生成的。

还是我需要将 PropertyChanged 事件及其方法添加到 MainWindow 中?

有什么帮助或建议吗?

谢谢

【问题讨论】:

  • 您能否添加作为网格数据源的类的代码?它是一个 Observable 集合吗?

标签: c# wpf entity-framework datagrid


【解决方案1】:

确保您遵循以下内容:

    public partial class MyEntity : INotifyPropertyChanged
    {
        // Methods
    }

    public class MyViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<MyEntity> _listEntities = new ObservableCollection<MyEntity>();
        public ObservableCollection<MyEntity> ListEntities
        {
            get { return this._listEntities; }
            set { /* code here... */}
        }
    }

在这种情况下,您可以将您的网格绑定到您的MyViewModel 实例的ListEntities。另外,尝试将绑定模式设置为TwoWay

【讨论】:

    【解决方案2】:

    您需要raisepropertychanged 来获取将通知 DiffValues 的两个属性,例如:

    public partial class Weight: INotifyPropertyChanged
    {
      //.....
      decimal  _benchmarkweight;
      decimal  _securityweight;
      public decimal Benchmark_Weight 
      {
         get{return _benchmarkweight;}
         set{
             _benchmarkweight=value; 
             OnPropertyChanged("Benchmark_Weight ");  
             // OnPropertyChanged("DiffValues");   //don't need if you raise it already in this.PropertyChanged 
            }
      }
      public decimal Security_Weight
      {
         get{return _securityweight;}
         set{
             _securityweight=value; 
             OnPropertyChanged("Security_Weight");  
            // OnPropertyChanged("DiffValues");  //don't need if you raise it already in this.PropertyChanged  
            }
      }
    
      //.....
    }
    

    编辑:抱歉没有意识到这是实体:

    Based on the discussion here你需要把模板里的WriteProperty方法改成下面这样,这样才会生成OnPropertyChanged的属性:

    void WriteProperty(string accessibility, string type, string name, string getterAccessibility, string setterAccessibility)
    {
    #>
        private <#=type#> _<#=name#>;
        <#=accessibility#> <#=type#> <#=name#> 
        { 
            <#=getterAccessibility#>get
            {
                return _<#=name#>;
            } 
            <#=setterAccessibility#>set
            {
                if (value != _<#=name#>)
                {
                    _<#=name#> = value;
                    OnPropertyChanged("<#=name#>");
                }
            }
        }
    
    <#+
    }
    

    【讨论】:

    • 感谢您的回复,我按照您上面的建议尝试了编译器错误。 Benchmark_Weight 和 Security_Weight 已在自动生成的文件中声明(第二个代码示例)。正如我在问题底部提到的,我认为我无法更改这些自动生成的属性。
    • 谢谢@Bolu 我要试试这个。我刚刚找到了一个类似(很好)的答案,它也更新了模板文件。 [链接]stackoverflow.com/questions/11010718/…
    • 也许我只需要使用 MVVM...我浏览了 .tt 并且 Context.tt 和 WriteProperty 不存在。
    猜你喜欢
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多