【发布时间】:2021-02-18 21:27:39
【问题描述】:
我有一个视图模型,它具有多个属性,这些属性数据绑定到多个控件。
当我在其中一个上引发 PropertyChanged 时,控件出乎意料地全部更新。我希望只有我提出事件的那个会更新。
对于我的表单,我有这个:
public partial class MainForm : Form
{
AmountCalculatorVM amountCalculatorVM;
public MainForm()
{
InitializeComponent();
}
private void setBindings()
{
textBoxTotalAmount.DataBindings.Add("Text", amountCalculatorVM, "TotalAmount");
textBoxAverage.DataBindings.Add("Text", amountCalculatorVM, "Average",true, DataSourceUpdateMode.Never,null, "#.00");
textBoxCount.DataBindings.Add("Text", amountCalculatorVM, "Count");
listBoxLineAmounts.DataSource = amountCalculatorVM.Amounts;
}
private void MainForm_Load(object sender, EventArgs e)
{
amountCalculatorVM = new AmountCalculatorVM();
setBindings();
}
private void buttonAddAmount_Click(object sender, EventArgs e)
{
if (int.TryParse(textBoxLineAmount.Text.Replace(",", ""), out int amount))
{
amountCalculatorVM.Amounts.Add(amount);
textBoxLineAmount.Text = "";
textBoxLineAmount.Focus();
}
}
private void buttonClear_Click(object sender, EventArgs e)
{
textBoxLineAmount.Text = "";
amountCalculatorVM.Amounts.Clear();
textBoxLineAmount.Focus();
}
}
然后,对于我的视图模型,我有这个:
class AmountCalculatorVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private readonly AmountList amounts;
public BindingSource Amounts { get; }
public int TotalAmount => amounts.TotalAmount;
public int Count => amounts.Count;
public decimal Average => amounts.Average;
public AmountCalculatorVM()
{
amounts = new AmountList();
Amounts = new BindingSource();
Amounts.DataSource = amounts;
Amounts.ListChanged += Amounts_ListChanged;
}
private void Amounts_ListChanged(object sender, ListChangedEventArgs e)
{
//Any one of these will cause all three textboxes to update in the form
//I would think that with Count and Average commented out, the Count and
//Average textboxes would not update.
OnPropertyChanged("TotalAmount");
//OnPropertyChanged("Count");
//OnPropertyChanged("Average");
//Using any other word will not
//OnPropertyChanged("SomeOtherRandomWord");
}
}
这里是 AmountList 类供参考:
class AmountList : List<int>
{
public int TotalAmount
{
get
{
int total = 0;
foreach (int amount in this)
{
total += amount;
}
return total;
}
}
现在,出乎意料的是,如果将一个项目添加到金额列表中,所有三个文本框都会更新,这会触发 ListChanged,然后依次触发 PropertyChanged 事件。
我触发 PropertyChanged 的三个属性中的哪一个无关紧要,但如果我使用不同的值,它将不起作用 - 它需要是 TotalAmount、Count 或 Average。
我无法理解这种行为。我预计只有绑定到 TotalAmount 的文本框会被更新,而不是其他两个,因为似乎没有通知他们发生了更新。
有什么想法吗?
【问题讨论】:
-
呃,您似乎是在说您有一个金额列表,以及一个用于 cailvialtobg 的机制,例如列表中所有金额的计数或平均值,而您不期望/想要平均值/count 当您在列表中添加/删除金额时更新。这看起来很奇怪?
-
并不是我不希望这种情况发生。只是它似乎不应该发生。我想了解,以免将来无意中更新控件。
-
不应该发生什么?很确定如果我制作了一个将平均值计算为 100 项的机制,如果我添加第 101 项,我希望它重新计算?
-
由于使用“TotalAmount”作为 eventArgs 参数引发了 PropertyChanged 事件,我看不到计数和平均文本框如何知道要更新。这个问题是关于尝试更多地理解数据绑定机制,而不是在这种特殊情况下的首选结果。
-
您已将控件绑定到您提到的三个属性。当您更改属性值(引发
PropertyChanged事件的属性)时,BindingSource 会传播PropertyChanged事件,因此所有绑定控件都会根据Current对象的值进行更新。 误解是您认为是您的Amounts_ListChanged处理程序导致(或应该导致)PropertyChanged事件:这已经发生,您的处理程序允许您在ListChanged事件时采取行动被提升了。
标签: c# .net winforms data-binding