Итак, я попытался использовать оба BindingList и BindingSource, но проблема одинакова с обоими.Источник привязки НЕ отражает новый/удаленный ряд, когда источник данных списка добавляет/удаляет элемент
Просто для фона: У меня есть приложение, в котором я получаю обновления на торговых объектах из api. Я получаю в реальном времени обновления от api (может быть add/update/remove updateType) и обрабатывать их в классе репозитория, который имеет списки каждого соответствующего типа объекта, которые все наследуют от родительского класса вызова DSO (для DataSourceObject).
Это хранилище имеет экземпляр в другой класс называется DataSource (я ссылаться на это позже.)
Так у меня есть несколько списков в моем Repository, который сидит в DataSource и все операции (добавление/удаление/обновление), работать в этих списках до этого момента.
Теперь, в моем пользовательском интерфейсе, у меня есть форма frmDashboard, которая вызывает форму frmDataWindow.
В этом frmDataWindow есть DataGridView, где я хочу показать свои различные объекты DSO childClass (3 примера - DSOPorfolio, DSOInstrument, DSOTrade).
Вот где у меня возникли вопросы, я пробовал разные методы, но я в настоящее время используют следующий подход:
я объявляю новый экземпляр frmDataWindow, в отдельном методе я передать ссылку на источник данных (или то, что я считаю ссылкой, потому что я понимаю, что C# передает все по ссылке в качестве значения по умолчанию) в экземпляр frmDataWindow. У этого DataSource уже есть репозиторий с загруженными списками моих BusinessObjects.
В экземпляр frmDataWindow я передаю тип объекта через enum (назовем его DSOType), который я хочу связать с DataGridView.
Затем я запускаю оператор switch, который присваивает список объектов DSO источнику привязки, преобразовывая его в соответствующий тип дочернего класса DSO (так что все свойства отображаются в DataGridView).
Просто заметьте, что я уже реализовал INotifyPropertyChanged во всех моих объектах DSO.
DataSource _ds;
BindingSource bs;
public void AssignDataSource(DataSource ds)
{
_ds = ds;
}
public void AssignDSO(DSOType type)
{
try
{
_dsoType = type;
dgvMain.Rows.Clear();
dgvTotal.Rows.Clear();
switch (_dsoType)
{
case DSOType.Portfolio:
{
bs = new BindingSource(_ds.DSORepository.GetDSOList(type).ConvertAll(x => (DSOPortfolio)x), null);
break;
}
case DSOType.Instrument:
{
bs = new BindingSource(_ds.DSORepository.GetDSOList(type).ConvertAll(x => (DSOInstrument)x), null);
break;
}
case DSOType.Trade:
{
bs = new BindingSource(_ds.DSORepository.GetDSOList(type).ConvertAll(x => (DSOTrade)x), null);
break;
}
case DSOType.ClosedTrade:
{
bs = new BindingSource(_ds.DSORepository.GetDSOList(type).ConvertAll(x => (DSOClosedTrade)x), null);
break;
}
case DSOType.Order:
{
bs = new BindingSource(_ds.DSORepository.GetDSOList(type).ConvertAll(x => (DSOOrder)x), null);
break;
}
case DSOType.Position:
{
bs = new BindingSource(_ds.DSORepository.GetDSOList(type).ConvertAll(x => (DSOPosition)x), null);
break;
}
default:
{
bs = null;
break;
}
}
string text = text = _ds.DSORepository.GetDSOList(type)[0].ObjectType.ToString();
dgvMain.DataSource = bs;
this.Text = text;
bs.ListChanged += new ListChangedEventHandler(bs_ListChanged);
settingsFullPath = settingsDirectory + @"\" + "DataGridView-" + this.Text + ".xml";
dgvMain.ReadOnly = true;
}
Таким образом, в этот момент, когда я запускаю мое приложение, я могу получить DataGridView населенного с соответствующими дочерними объектами DSO И когда происходит изменение в какой-то объект, он отражает должным образом и обновлениями в DataGridView. ОДНАКО, когда я добавляю/удаляю объект из своего списка в моем репозитории, скажем, новый DSOTrade, в то время как окно открыто, я ожидаю, что это изменение будет отражено в моем bindSource, где должна быть добавлена новая строка или строка должен исчезнуть в зависимости от действия, предпринятого в списке, который привязан к BindingSource.
Этого не происходит.
Когда я беру любое действие, остается такое же количество строк.
Я выполнил дополнительный этап тестирования (просто добавил клик) и чтобы я мог добавить точку останова и сравнить мои привязкиSource/Datagridview/и список, из которого происходят объекты. Кажется, что список Binding не изменяет его количество, чтобы отразить новый/удаленный элемент.
Допустим, что изначально было 3 строки, и теперь я добавил один в свой список. Затем я запускаю свой тест, установив это событие click, я вижу, что список (который находится в репозитории) правильно обновлен и теперь имеет счет 4, а BindingSource (и, конечно, DataGridView) все еще имеет кол-во 3.
Если бы я должен был удалить товар (скажем, счет 3 снова). Я запускаю тот же тест, и у List есть счет 2, а BindingSource по-прежнему имеет значение 3.
Еще одна важная вещь, которую следует отметить, заключается в том, что мои DSO имеют свойство, в котором указывается последний тип обновления. Когда я собираюсь удалить элемент из списка, UpdateType для этого свойства изменится на «DELETE». Это изменение действительно отражено в моем DataGridView, который говорит мне, что изменение свойства все еще проходит через BidnginSOurce, но добавление/удаление элемента не происходит через BindingSource.
У кого-нибудь есть мысли? Отрывая мои волосы от этого.
Сообщите мне, если мне нужно разместить дополнительную информацию.
Спасибо.
Edited в ответ на вопросы Марка Gravell в: В моем хранилище настоящее время я использую System.Collections.Generic.List, Для каждого из моих списков, они являются List (родительский класс для своих объектов).
Я в настоящее время не использую BindingList в своем подходе, я непосредственно назначаю My List новому BindingSource, как показано выше, однако я также попробовал BindingList и получал те же результаты, после этого редактирования я сделаю другое редактирование после Я повторяю с BindingList и выставляю свой код.
В настоящее время я обрабатываю событие ListChanged следующим образом. Я хотел обновить свой DataGridView (dgvMain) на ListChangedType.ItemAdded или ListChangedType.ItemDeleted (хотя обновление также не помогает, я тестировал обновление при событии с нажатием кнопки), однако событие всегда, кажется, срабатывает как ListChangedType .ItemChanged.
Когда я добавляю или удаляю элемент, НИЧЕГО не срабатывает в списке, измененном событии.
Ниже вы видите код обработки событий - это тики обновлений с сервера API, которые в настоящее время работают и работают в течение новой недели.
void bs_ListChanged(object sender, ListChangedEventArgs e)
{
Debug.WriteLine("sender is= " + sender.ToString());
Debug.WriteLine("bs.Datasource= " + bs.DataSource);
Debug.WriteLine("e.ListChangedType = " + e.ListChangedType);
if (e.ListChangedType == ListChangedType.ItemAdded || e.ListChangedType == ListChangedType.ItemDeleted)
{
SystemControlInvoker.InvokeControl(dgvMain, RefreshDGV);
}
}
отправитель = System.Windows.Forms.BindingSource bs.Datasource = System.Collections.Generic.List 1[Pharaoh_Dashboard.DSOTrade] e.ListChangedType = ItemChanged sender is= System.Windows.Forms.BindingSource bs.Datasource= System.Collections.Generic.List
1 [Pharaoh_Dashboard.DSOTrade] e.ListChangedType = ItemChanged отправитель = System.Windows. Forms.BindingSource bs.Datasource = System.Collections.Generic.List 1[Pharaoh_Dashboard.DSOTrade] e.ListChangedType = ItemChanged sender is= System.Windows.Forms.BindingSource bs.Datasource= System.Collections.Generic.List
1 [Pharaoh_Dashboard.DSOTrade] e.ListChangedType = ItemChanged отправитель = System.Windows.Forms.BindingSource bs.Datasource = System.Collections.Generic. Список 1[Pharaoh_Dashboard.DSOTrade] e.ListChangedType = ItemChanged sender is= System.Windows.Forms.BindingSource bs.Datasource= System.Collections.Generic.List
1 [Pharaoh_Dashboard.DSOTrade] e.ListChangedTy pe = ItemChanged
Я реализую INotifyPropertyChanged следующим образом.
public abstract class DSO : IDisposable, INotifyPropertyChanged
{
protected bool _isCreationComplete;
string _dataSourceObjectID;
string _dataSourceID;
protected string _portfolioName;
int _dsoInstance = -1;
protected DSOType _objectType;
protected DSOUpdateType _updateType;
public string DataSourceObjectID
{
get { return _dataSourceObjectID; }
set
{
_dataSourceObjectID = value;
NotifyPropertyChanged("DataSourceObjectID");
}
}
public string DataSourceID
{
get { return _dataSourceID; }
set
{
_dataSourceID = value;
NotifyPropertyChanged("DataSourceID");
}
}
public string PortfolioName
{
get { return _portfolioName; }
set
{
_portfolioName = value;
NotifyPropertyChanged("PortfolioName");
}
}
public DSOType ObjectType
{
get { return _objectType; }
set
{
_objectType = value;
NotifyPropertyChanged("ObjectType");
}
}
public DSOUpdateType UpdateType
{
get { return _updateType; }
set
{
_updateType = value;
NotifyPropertyChanged("UpdateType");
}
}
public bool CreationIsComplete
{
get { return _isCreationComplete; }
set
{
_isCreationComplete = value;
NotifyPropertyChanged("CreationIsComplete");
}
}
public DSO()
{
_isCreationComplete = false;
}
public void SetDSOInstance(int dsoInstance)
{
//do this so it can only be assigned once
if (_dsoInstance == -1)
{
_dsoInstance = dsoInstance;
_dataSourceObjectID = _dataSourceID + "-" + _objectType + "-" + _dsoInstance;
}
}
public void Dispose()
{
//throw new NotImplementedException();
}
protected void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class DSOTrade : DSO
{
int _amount;
string _buySell;
string _instrumentID;
decimal _openRate;
DateTime _openTime;
decimal _commission;
decimal _rolloverInterest;
string _tradeID;
decimal _usedMargin;
decimal _close;
decimal _grossPnL;
decimal _netPnL;
decimal _limit;
decimal _pnl;
decimal _stop;
string _instrument;
bool _isChangeFromInstrumentTick;
TimeSpan _tradeTimeLength;
public string TradeID
{
get { return _tradeID; }
set
{
if (value != _tradeID)
{
_tradeID = value;
NotifyPropertyChanged("TradeID");
}
}
}
public string BuySell
{
get { return _buySell; }
set
{
if (value != _buySell)
{
_buySell = value;
NotifyPropertyChanged("BuySell");
}
}
}
public string InstrumentID
{
get { return _instrumentID; }
set
{
if (value != _instrumentID)
{
_instrumentID = value;
NotifyPropertyChanged("InstrumentID");
}
}
}
public int Amount
{
get { return _amount; }
set
{
if (value != _amount)
{
_amount = value;
NotifyPropertyChanged("Amount");
}
}
}
public decimal OpenRate
{
get { return _openRate; }
set
{
if (value != _openRate)
{
_openRate = value;
NotifyPropertyChanged("OpenRate");
}
}
}
public decimal Commission
{
get { return _commission; }
set
{
if (value != _commission)
{
_commission = value;
NotifyPropertyChanged("Commission");
}
}
}
public decimal RolloverInterest
{
get { return _rolloverInterest; }
set
{
if (value != _rolloverInterest)
{
_rolloverInterest = value;
NotifyPropertyChanged("RolloverInterest");
}
}
}
public decimal UsedMargin
{
get { return _usedMargin; }
set
{
if (value != _usedMargin)
{
_usedMargin = value;
NotifyPropertyChanged("UsedMargin");
}
}
}
public DateTime OpenTime
{
get { return _openTime; }
set
{
if (value != _openTime)
{
_openTime = value;
NotifyPropertyChanged("OpenTime");
}
}
}
//Calculated
public decimal Close
{
get { return _close; }
set
{
if (value != _close)
{
_close = value;
NotifyPropertyChanged("Close");
}
}
}
public decimal PnL
{
get { return _pnl; }
set
{
if (value != _pnl)
{
_pnl = value;
NotifyPropertyChanged("PnL");
}
}
}
public decimal GrossPnL
{
get { return _grossPnL; }
set
{
if (value != _grossPnL)
{
_grossPnL = value;
NotifyPropertyChanged("GrossPnL");
}
}
}
public decimal NetPnL
{
get { return _netPnL; }
set
{
if (value != _netPnL)
{
_netPnL = value;
NotifyPropertyChanged("NetPnL");
}
}
}
public decimal Limit
{
get { return _limit; }
set
{
if (value != _limit)
{
_limit = value;
NotifyPropertyChanged("Limit");
}
}
}
public decimal Stop
{
get { return _stop; }
set
{
if (value != _stop)
{
_stop = value;
NotifyPropertyChanged("Stop");
}
}
}
public string Instrument
{
get { return _instrument; }
set
{
if (value != _instrument)
{
_instrument = value;
NotifyPropertyChanged("Instrument");
}
}
}
public TimeSpan TradeTimeLength
{
get { return _tradeTimeLength; }
set
{
if (value != _tradeTimeLength)
{
_tradeTimeLength = value;
NotifyPropertyChanged("TradeTimeLength");
}
}
}
public bool IsChangeFromInstrumentTick
{
get { return _isChangeFromInstrumentTick; }
set
{
if (value != _isChangeFromInstrumentTick)
{
_isChangeFromInstrumentTick = value;
NotifyPropertyChanged("IsChangeFromInstrumentTick");
}
}
}
public DSOTrade()
{
_objectType = DSOType.Trade;
}
}
INotifyPropertyChanged не используется для списков; какой у вас тип списка? Он реализует IBindingList? И добавлен ли ListChanged для ваших изменений? –
@Marc Gravell: Marc I отредактировал мое сообщение, чтобы ответить на ваши вопросы. Пожалуйста, дайте мне знать, если это не ясно или вам нужна дополнительная информация. – xSquared