数据绑定到计算字段

发布于 2024-10-26 22:32:58 字数 1577 浏览 3 评论 0原文

我遇到了一个小问题,我试图将 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 不是数据库表上的字段,因此我为此创建了一个部分类。

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

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

I'm running into a small problem where I'm trying to bind a DataTextColumn of a DataGrid to a Calculated Field.

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>

Where Student is a Entity object with one small addition. TotalCosts isn't a field on the db tables, so I created a partial class for this.

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

The problem I'm experiencing is that TotalCosts is not automatically updating when you fill in any of the other fields. My guess it is because it is not listed as a dependency property. How do I resolve this for a property where there is no set ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

淡淡離愁欲言轉身 2024-11-02 22:32:58

我假设 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"));
        }
    }

}

I'm assuming Student implements INotifyPropertyChanged. what you have to do is to register to the PropertyChanged Event for LodgingCosts + RegistrationCosts + TravelCosts + DiningCosts, and raise the PropertyChanged event for TotalCosts.

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"));
        }
    }

}
长伴 2024-11-02 22:32:58

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

You can call OnPropertyChanged("TotalCosts") in the setters of each property that TotalCosts depends on, it will refresh the binding

梦里的微风 2024-11-02 22:32:58

你好,我想我可以帮助你,我有 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 键移动到 C 列,值 2 就会自动出现
无需单击其他行或按 Enter 键。

ColumnC 是一个计算列,具有表达式 (ColumnaA/ColumnaB) 和类型
系统.十进制。

这是我的 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>

Hello o think i can help you i have this code for a data base in sqlServer
and i have a Data source with a DataSet for my Data Base

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);
        }
    }
}

With this trick the column C is calculated automatically after i have a value
in columns A and B for example if i put 10 in columna A and 5 in column B
then i just press Tab Key to move to the columnC and the value 2 appears automatically
no need to click other row or press enter.

ColumnC is a calculated column whit the expression (ColumnaA/ColumnaB) and of type
System.Decimal.

And there is my xaml code:

<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>
夜吻♂芭芘 2024-11-02 22:32:58

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

Just change the DataSourceUpdateMode to OnPropertyChanged when you create DataBinding to the TotalCosts property.

撩心不撩汉 2024-11-02 22:32:58

您需要在类上实现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 将找到具有该值的计算字段..
希望它能帮助你..
谢谢,
哈维克

You need to implement the INotifyPropertyChanged on the class. Here is the Example:

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 code:

<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>

Test:

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)
{

}

type something in the 2 textboxes..and on the Button click see the value of the person P1 ..u will find the calculated field with the value..
hope it helps u..
Thanks,
BHavik

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文