开发者

strange problem using dataGridView and BindingSource [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center. Closed 11 years ago.

I am getting a very strange problem with DataGridView. I have 3 grids in my custom control. I am using this implementation: I have linked the datagridview with the bindingsource using the designer. The user of my control call initialize method with some parameters. The control populate 3 internal lists (actually 2 lists and dictionary of objects). Af开发者_StackOverflow中文版ter the lists are populated I assign the lists to the binding sources.

Two grids are working fine, however one of them is not displaying anything (the underlying list contain data). If I change this line:

bindingSource.DataSource = myList;

to

bindingSource.DataSource = myList;
datagridView.DataSource = null;
datagridView.DataSource = bindingSource;

the grid will display the rows, however any event on the grid will raise an exception (IndexOutOfRangeException "Index -1 does not have a value." in this line of code).

This is the relevant code:

    public partial class DisplayTradeSplitValuesControl : UserControl
    {
        List<TradeSplittingRatio> templateDatasource_ = new List<TradeSplittingRatio>();
        List<TradeSplittingRatio> fundsDatasource_ = new List<TradeSplittingRatio>();
        Dictionary<string,List<TradeSplittingRatio>> portfolioDatasource_ =
            new Dictionary<string,List<TradeSplittingRatio>>();

        private string instrumentName_ = string.Empty;

        private RoundingRuleAbstract roundingRule_;

        public DisplayTradeSplitValuesControl()
        {
            InitializeComponent();
        }

        public void Initialize(string portfolioName, string instrumentName, double value)
        {
            ConfigManager.GetConfigManager().LoadPortfolioCache();
            ConfigManager.GetConfigManager().LoadPortfolioRatioCache();            
            instrumentName_ = instrumentName;
            roundingRule_ = GetGranularity(instrumentName_);
            PopulateTemplateDatasource(portfolioName, value);
            PopulateFundDatasource(portfolioName, value);
            PopulatePortfolioAndManagedAccountDatasource();
            PopulateGrid();
        }

        private void PopulateGrid()
        {
            templateSplittingRatioBindingSource.DataSource = templateDatasource_;
            fundTradeSplittingRatioBindingSource.DataSource = fundsDatasource_;
            templateDataGridView.Refresh();
            //fundsDataGridView.DataSource = null; //not working hack!!!
            //fundsDataGridView.DataSource = fundTradeSplittingRatioBindingSource.DataSource;
            fundsDataGridView.Refresh();
            if (fundsDatasource_.Count > 0)
            {
                string portfolioName = fundsDatasource_[0].ToPortfolio;
                portfolioTradeSplittingRatioBindingSource.DataSource = portfolioDatasource_[portfolioName];

                portfolioDataGridView.Refresh();
            }

        }

        private void PopulateTemplateDatasource(string portfolioName, double value)
        {
            templateDatasource_.Clear();
            TradeSplittingRatio template = new TradeSplittingRatio(string.Empty, portfolioName, 0, value, 0);
            templateDatasource_.Add(template);
        }

        private void PopulateFundDatasource(string portfolioName, double value)
        {
            fundsDatasource_.Clear();
            if (ConfigManager.GetConfigManager().ActivePortfolioCache.ContainsKey(portfolioName) == true)
            {
                Portfolio portfolio = ConfigManager.GetConfigManager().ActivePortfolioCache[portfolioName];
                if (ConfigManager.GetConfigManager().ActivePortfolioRatioCache.ContainsKey(portfolio) == true)
                {
                    List<KeyValuePair<Portfolio, double>> portfolioRatio =
                        ConfigManager.GetConfigManager().ActivePortfolioRatioCache[portfolio];

                    foreach (KeyValuePair<Portfolio, double> ratio in portfolioRatio)
                    {
                        fundsDatasource_.Add(new TradeSplittingRatio(portfolioName,
                                                               ratio.Key.Identifier,
                                                               ratio.Value,
                                                               roundingRule_.Calculate(new Ratio(ratio.Value).Calculate(value)),
                                                               roundingRule_.Granularity));
                    }
                }
            }
        }

        private void PopulatePortfolioAndManagedAccountDatasource()
        {
            portfolioDatasource_.Clear();

            List<TradeSplittingRatio> cloneFundsDatasource = new List<TradeSplittingRatio>();
            foreach (TradeSplittingRatio fund in fundsDatasource_)
            {
                cloneFundsDatasource.Add((TradeSplittingRatio)fund.Clone());
            }

            foreach (TradeSplittingRatio fund in cloneFundsDatasource)
            {
                if (portfolioDatasource_.ContainsKey(fund.ToPortfolio) == false)
                    portfolioDatasource_.Add(fund.ToPortfolio,new List<TradeSplittingRatio>());

                Portfolio portfolio = ConfigManager.GetConfigManager().ActivePortfolioCache[fund.ToPortfolio];
                List<KeyValuePair<Portfolio, double>> portfolioRatio =
                    ConfigManager.GetConfigManager().ActivePortfolioRatioCache[portfolio];

                foreach (KeyValuePair<Portfolio, double> ratio in portfolioRatio)
                {
                    portfolioDatasource_[fund.ToPortfolio].Add(new TradeSplittingRatio
                        (fund.ToPortfolio,
                        ratio.Key.Identifier,
                        ratio.Value,
                        roundingRule_.Calculate(new Ratio(ratio.Value).Calculate(fund.Amount)),
                        roundingRule_.Granularity));
                }
            }
        }

        private RoundingRuleAbstract GetGranularity(string instrumentName)
        {
            ConfigManager.GetConfigManager().LoadBondCache();
            ConfigManager.GetConfigManager().LoadInstrumentCache();

            if (ConfigManager.GetConfigManager().ActiveInstrumentCache.ContainsKey(instrumentName))
            {
                if (string.Equals(ConfigManager.GetConfigManager().ActiveInstrumentCache[instrumentName].InstrumentType.Identifier,"CASH") ||
                    string.Equals(ConfigManager.GetConfigManager().ActiveInstrumentCache[instrumentName].InstrumentType.Identifier, "FX"))
                {
                    return new RoundingRule.RoundHalfUpRule(ConfigManager.GetConfigManager().ActiveInstrumentCache[instrumentName].Currency.Granularity);
                }
                if (ConfigManager.GetConfigManager().ActiveBondCache.ToList().
                        Where(c => c.Value.InstrumentId == ConfigManager.GetConfigManager().ActiveInstrumentCache[instrumentName].InstrumentId).Count() > 0)
                {
                    return new RoundingRule.RoundHalfUpRule(
                        ConfigManager.GetConfigManager().ActiveBondCache.ToList().
                        Where(c => c.Value.InstrumentId == ConfigManager.GetConfigManager().ActiveInstrumentCache[instrumentName].InstrumentId).First().Value.Granularity);
                }
            }
            return new RoundingRule.RoundHalfUpRule(1.0); 
        }

        private void fundsDataGridView_SelectionChanged(object sender, EventArgs e)
        {
            if (fundsDataGridView.Focused)
            {
                TradeSplittingRatio fund = (TradeSplittingRatio)fundsDataGridView.SelectedRows[0].DataBoundItem;
                portfolioTradeSplittingRatioBindingSource.DataSource = portfolioDatasource_[fund.ToPortfolio];
                portfolioDataGridView.Refresh();                
            }
            //Validate();
        }
    //other stuff not important
    }
}

Thanks for your help.


I didn't get through all the code, I skipped to the end and this part jumped out at me:

        private void fundsDataGridView_SelectionChanged(object sender, EventArgs e)
        {
            if (fundsDataGridView.Focused)
            {
                TradeSplittingRatio fund = (TradeSplittingRatio)fundsDataGridView.SelectedRows[0].DataBoundItem;
                portfolioTradeSplittingRatioBindingSource.DataSource = portfolioDatasource_[fund.ToPortfolio];
                portfolioDataGridView.Refresh();                
            }
            //Validate();
        }

You access DataGridView.SelectedRows[0] even though you have not checked to see if it contains any items. It's entirely possible for SelectionChanged to fire when the selection becomes empty (usually because the data source was changed or cleared).

If you fail to test boundaries here, it's likely you are failing to do so elsewhere. The error message you have says exactly that: Something, probably an event, was raised with an index of -1 and you're attempting to access row #-1, which of course doesn't exist.

Updated

Another potential problem with the code I quoted is the Focused check. I'm not sure why you care about focus here, but the DGV uses a (single) child control in the cell that is currently being edited by the user. If that "editing control" has focus, DGV.Focused will be false.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜