【发布时间】:2021-11-03 21:21:44
【问题描述】:
我有一个实现 INotifyChanged 的简单 OHLC 对象。每个 OHLC 对象都与特定的蜡烛相关,并且是列表的一部分。每个 List 都与特定股票相关,并存储在 ConcurrentDictionary
我正在尝试将每只股票的最后一根蜡烛数据绑定到数据网格视图。这就是我设置数据绑定的方式。不是很优雅!
ConcurrentDictionary<string, List<OHLC>> candles= new ConcurrentDictionary<string, List<OHLC>>();
BindingList<OHLC> LastCandles = new BindingList<OHLC>();
. . .
form1.dataGridView1.DataSource = LastCandles;
. . .
public void OnUpdate()
{
//Update the appropriate candles
. . .
//Pull out the last candle by symbol and re-bind
BindingList<OHLC> lastBySymbol = new BindingList<OHLC>();
foreach (KeyValuePair<string, List<OHLC>> dict in candles)
{
if (dict.Value.Count > 0)
{
lastBySymbol.Add(dict.Value.Last());
}
}
LastCandles = lastBySymbol;
form1.dataGridView1.BeginInvoke((MethodInvoker)delegate
{
form1.dataGridView1.DataSource = LastCandles;
form1.dataGridView1.Refresh();
});
}
在这里设置数据绑定的最佳方式是什么,这样我就可以专注于更新集合而不必在每次更新时重新绑定?我可以限制对 datagridview.Refresh() 的调用,因此它不会在每次原子更新时重新绘制,但不想重新绑定。
我知道如何将数据绑定一次到自定义对象的 BindingList 并使用 INotifyPropertyChanged 和对 datagridview.Refresh() 的简单调用将更新传播到 UI。我还可以在 XAML 中找到一些示例,这些示例显示了与 BindingList 中最后一项的数据绑定。但我找不到任何绑定到列表字典的“last-per-key”的示例。
如果能提供任何帮助,我将不胜感激。
【问题讨论】:
-
唯一重要的是你如何在你的
ConcurrentDictionary<string, List<OHLC>>中设置List<OHLC>,这似乎是一个辅助线程。如果您不完全替换List<OHLC>,而是创建一个新对象,而只是更新现有成员,则 Binding 也可以跨线程工作。如果您改为替换字典中的List<OHLC>,创建一个新对象,数据绑定当然不起作用,只是因为您已经销毁了它。 -- 您可以将 BindingList 设置为,例如,LastCandles.Add(Candles["First"].Last()); LastCandles.Add(Candles["Second"].Last()); [...] -
...当您第一次初始化 BindingList 时,可能在您设置 DataGridView 的 DataSource 之前。 -- 如果你在字典中添加了新的 Keys,还要将新的
Last()对象添加到 BindingList 中(这个对象稍后会更新,从辅助线程)。 -- 这:form1.dataGridView1.[...]根本不是什么好东西。另外,不要BeginInvoke()一个Control,总是使用父Form容器作为marshaller。 -
我可以尝试在初始化期间填充 ConcurrentDictionary,然后用每个键的最后一个 OHLC 对象填充 BindingList,然后将数据源设置为 BindingList。但是当一个新的蜡烛到达并且一个新的 OHLC 对象被添加到 ConcurrentDictionary 中特定键的 List
时,绑定不会丢失,因为 Last() 会改变吗? -
唯一重要的是如何在 ConcurrentDictionary
> 中设置 List:是的,确实如此。这就是介绍的原因。如果是这种情况,您可以在将新成员添加到 Dictionary 或 Last()内部列表更改的条目时使用IProgress<T>委托来更新 UI(如果您修改列表成员的属性值则不能)。委托方法可以是:private void UpdateLastCandles() { LastCandles.Clear(); foreach (var list in Candles.Values) { LastCandles.Add(list.Last()); }。您只是在添加引用。 -
按照这个逻辑,你可以使用一个中间对象进行数据绑定:另一个只包含一个 List 成员的 Dictionary,它使用 main 中每个 List 的
Last()条目的属性值进行更新收藏。在这种情况下,您无需执行任何操作,数据绑定将永远有效,无需直接更新LastCandlesBindingList 的内容。
标签: c# winforms data-binding