2011-05-13 53 views
3

我得到一个非常奇怪的问题与DataGridView。我的自定义控件中有3个网格。我正在使用这个实现:我已经使用设计器将datagridview与bindingsource链接起来了。我的控制调用的用户使用一些参数初始化方法。该控件填充3个内部列表(实际上是2个列表和对象字典)。列表填充后,我将列表分配给绑定源。奇怪的问题,使用dataGridView和BindingSource

两个网格工作正常,但其中一个不显示任何内容(底层列表包含数据)。如果我改变这一行:

bindingSource.DataSource = myList; 

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

网格将显示该行,但对电网的任何事件将引发异常(IndexOutOfRangeException“指数-1不具有价值。 “在这行代码中)。

这是相关代码:

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

感谢您的帮助。

回答

1

我没有通过所有的代码得到的,我跳到底,这一部分我跳了出来:

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

您访问DataGridView.SelectedRows[0]即使你没有检查,看它是否包含任何项目。当选择变空时(通常是因为数据源被更改或清除),SelectionChanged完全可能触发。

如果您未能在此处测试边界,则很可能您在其他地方没有这样做。你所说的错误信息正是这样描述的:某些东西,可能是一个事件,是以-1的索引引发的,而你试图访问第-1行,这当然不存在。

更新

与代码的另一个潜在的问题,我引用的是焦点检查。我不确定为什么你在乎这里的重点,但DGV在用户正在编辑的单元格中使用(单个)子控件。如果该“编辑控件”具有焦点,则DGV.Focused将为false。

+0

谢谢,你有一个好点(我会放一个警卫)。然而,这不是我的问题的原因。我在方法内部放置了一个断点,并且断点没有被击中。 – 2011-05-13 14:53:54

+0

@Alessandro:我想我很清楚,我指出的是与你的问题相关。我继续说“有些事情,可能是一个事件......”。换句话说,问题不在我指出的地方。我指出你的代码不能检查它的假设。在别的地方,你有更多的代码不能检查假设。 – Tergiver 2011-05-13 15:06:47