【问题标题】:DataBinding to Calculated Field数据绑定到计算字段
【发布时间】:2020-11-13 20:09:32
【问题描述】:

我遇到了一个小问题,我试图将 DataGrid 的 DataTextColumn 绑定到计算字段。

WPF

<DataGrid ItemsSource="{Binding Path=CurrentRoster, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
          AutoGenerateColumns="False" 
          AlternatingRowBackground="Gainsboro"  
          AlternationCount="2">
    <DataGrid.Columns>
    <DataGridComboBoxColumn Header="Student Enrolled"
                            ItemsSource="{Binding Source={StaticResource AvailableStudents}}"
                            SelectedItemBinding="{Binding Path=Student}">
    </DataGridComboBoxColumn>
    <DataGridTextColumn Header="Registration" Binding="{Binding Path=RegistrationCosts, StringFormat='{}{0:C}'}"/>
    <DataGridTextColumn Header="Lodging" Binding="{Binding Path=LodgingCosts, StringFormat='{}{0:C}'}"/>
    <DataGridTextColumn Header="Travel" Binding="{Binding Path=TravelCosts, StringFormat='{}{0:C}'}"/>
    <DataGridTextColumn Header="Dining" Binding="{Binding Path=DiningCosts, StringFormat='{}{0:C}'}"/>
    <DataGridTextColumn Header="Total Costs" IsReadOnly="True" Binding="{Binding Path=TotalCosts, StringFormat='{}{0:C}'}"/>
</DataGrid.Columns>

Student 是一个 Entity 对象,有一个小的添加。 TotalCosts 不是 db 表上的字段,因此我为此创建了一个部分类。

public partial class Student
{
    public  Decimal TotalCosts
    {
        get { return (LodgingCosts + RegistrationCosts + TravelCosts + DiningCosts); }
    }
}

我遇到的问题是,当您填写任何其他字段时,TotalCosts 不会自动更新。我的猜测是因为它没有被列为依赖属性。对于没有设置的属性,我该如何解决这个问题?

【问题讨论】:

    标签: c# wpf data-binding entity-framework-4


    【解决方案1】:

    我假设 Student 实现了 INotifyPropertyChanged。您需要做的是注册到 LodgingCosts + RegistrationCosts + TravelCosts + DiningCosts 的 PropertyChanged 事件,并为 TotalCosts 引发 PropertyChanged 事件。

    public partial class Student
    {
        public Decimal TotalCosts
        {
            get { return (LodgingCosts + RegistrationCosts + TravelCosts + DiningCosts); }
        }
    
        public Student()
        {
            this.PropertyChanged += new PropertyChangedEventHandler(Student_PropertyChanged);
        }
    
        void Student_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "LodgingCosts" ||
                e.PropertyName == "RegistrationCosts" ||
                e.PropertyName == "TravelCosts" ||
                e.PropertyName == "DiningCosts")
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("TotalCosts"));
            }
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      你可以在TotalCosts所依赖的每个属性的setter中调用OnPropertyChanged("TotalCosts"),它会刷新绑定

      【讨论】:

      • 我回答后你为什么要回答这个问题?
      • 为什么不呢?这不是同一个答案(尽管它也使用 OnPropertyCHanged)。我认为最好在设置器中执行此操作,而不是处理 PropertyChanged 事件。我不喜欢订阅我自己的活动的想法......
      • 是的。现在我注意到了。我假设 Student 是自动生成的,因此您无法更改 Setter。我更喜欢你的想法,但 99% 的情况下它不适用(使用 EF、WCF 等时)
      • 确实,尽管 EF 生成的类提供了部分方法,您可以实现这些方法以在属性更改时执行自定义操作
      【解决方案3】:

      您好,我想我可以帮助您,我有此代码用于 sqlServer 中的数据库 我有一个数据源和我的数据库的数据集

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Data;
      using System.Windows.Documents;
      using System.Windows.Input;
      using System.Windows.Media;
      using System.Windows.Media.Imaging;
      using System.Windows.Navigation;
      using System.Windows.Shapes;
      
      using TestDeDataGrid.TestDSTableAdapters;
      
      namespace TestDeDataGrid
      {
      
          public partial class MainWindow : Window
          {
              //private ICollection<TablaTest> registros;
      
              public MainWindow()
              {
                  InitializeComponent();
      
                  TestDS ds = new TestDS();
                  TablaTestTableAdapter adapter = new TablaTestTableAdapter();
                  adapter.Fill(ds.TablaTest);
      
      
                  TablaTestGrid.ItemsSource = ds.TablaTest.DefaultView;
              }
      
      
              private void TablaTestGrid_CurrentCellChanged(object sender, EventArgs e)
              {
                  if ((String)(((DataGrid)sender).CurrentColumn.Header) == "A/B")
                      ((DataGrid)sender).CommitEdit(DataGridEditingUnit.Row, true);
              }
          }
      }
      

      有了这个技巧,在我有一个值之后,C列就会自动计算出来 例如,在 A 列和 B 列中,如果我在 A 列中放入 10,在 B 列中放入 5 然后我只需按 Tab 键移动到 columnC 并且值 2 会自动出现 无需点击其他行或回车。

      ColumnC 是一个计算列,其表达式为 (ColumnaA/ColumnaB),类型为 System.Decimal。

      还有我的 xaml 代码:

      <DataGrid Name="TablaTestGrid" Grid.Row="1" AutoGenerateColumns="False"                    
                    CurrentCellChanged="TablaTestGrid_CurrentCellChanged">
              <DataGrid.Columns>
                  <DataGridTextColumn Header="ID" Binding="{Binding Path=IdTablaTest}" IsReadOnly="True"></DataGridTextColumn>
                  <DataGridTextColumn Header="Col A" Binding="{Binding Path=ColumnaA}"></DataGridTextColumn>
                  <DataGridTextColumn Header="Col B" Binding="{Binding Path=ColumnaB}"></DataGridTextColumn>
                  <DataGridTextColumn Header="A/B" Binding="{Binding Path=ColumnaC}" IsReadOnly="True" ></DataGridTextColumn>               
                  <DataGridTextColumn Header="TestOnly"></DataGridTextColumn>
              </DataGrid.Columns>
          </DataGrid>
      

      【讨论】:

        【解决方案4】:

        只需将DataBinding 创建为TotalCosts 属性时,将DataSourceUpdateMode 更改为OnPropertyChanged

        【讨论】:

        • 嗨,汤姆。感谢您的有用回答。请牢记以下准则以提供完整答案。 Tips for Answering。亲切的问候。
        【解决方案5】:

        你需要在类上实现INotifyPropertyChanged。这是示例:

        public class Person : INotifyPropertyChanged
        {
            //public int Id
            //{ get; set; }
        
            //public string Name { get; set; }
        
            private int _Id;
        
            public int Id
            {
                get { return _Id; }
                set { _Id = value;
                RaisePropertyChanged("Id");
                }
            }
        
            private string _EmpNo
            {
                get
                {
                    return Id.ToString() + Name.ToString();
                }
            }
        
            private string _Name;
        
            public string Name
            {
                get { return _Name; }
                set
                {
                    _Name = value;
                    RaisePropertyChanged("Name");
                }
            }
        
            private void RaisePropertyChanged(string property)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        
            public event PropertyChangedEventHandler PropertyChanged;
        }
        

        XAML 代码:

        <DockPanel>
            <TextBox Text="{Binding P1.Id}" Height="50" Width="100" DockPanel.Dock="Top" />
            <TextBox Text="{Binding P1.Name}" Height="50" Width="100" DockPanel.Dock="Top" />
            <Button Content="OK" Click="Button_Click" DockPanel.Dock="Bottom"/>
        </DockPanel>
        

        测试:

        public TestWindow()
        {
            InitializeComponent();
        
            this.DataContext = this;
        }
        
        private Person _P1 = new Person();
        
        public Person P1
        {
            get { return _P1; }
            set { _P1 = value; }
        }
        
        private void Button_Click(object sender, RoutedEventArgs e)
        {
        
        }
        

        在 2 个文本框中输入内容..然后在按钮上单击查看人 P1 的值 ..u 将找到具有该值的计算字段.. 希望它可以帮助你.. 谢谢, 哈维克

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-30
          • 2020-09-11
          • 2023-03-26
          • 1970-01-01
          • 2018-02-06
          • 1970-01-01
          相关资源
          最近更新 更多