C# a Step by Step Beginners Tutorial

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rui Rodrigues
    Junior Member
    • Mar 2011
    • 3

    #31
    After Step 62 I get an error at MenuTree.cs at this line:

    UsrMsg( string.Format( "User Clicked the Market: ({0}), ID = ({1}), ", tNode.Text, tNode.m_id ) );

    NullReferenceException was unhandled - Object reference not set to an instance of an object

    If I take de "UsrMsg" and return to "Debug.WriteLine" the error is ignored and another will appear at

    lock( e_mData.varsLock )


    Everything compiled just fine until now... Any thoughts?


    BTW also had to add :

    using BetfairAPI.BFGlobal;
    using BetfairAPI.BFExchange;


    to CMarketData.cs so I wouldn't get errors concerning

    GetMarketResp
    GetMarketPricesResp
    GetMarketPricesCompressedResp


    Found it odd as it is in the same name space But this way it works


    Any comments will be most appreciated.

    Comment

    • Drifter
      Junior Member
      • Mar 2009
      • 30

      #32
      Rui - there are small (and I emphasise small) coding leaps you need to make. Whether Escapee has missed a couple of things deliberately, or just in transcription isn't really important. You can see that at least 3 of us managed to get there, and I would suggest there is more to be gained by chasing down the error message than being led blindly. If you are *really* stuck, then I am sure someone will respond if you post again - but if you can't solve the small problems that are there, you may struggle to actually apply any of this.

      Comment

      • Escapee
        Junior Member
        • Feb 2009
        • 51

        #33
        wow, come back after a few days break in europe and very pleased to see a few screen shots....


        twisterpb
        "when i look at the values on the webpage for an event and look into my code, the values are mostly not the same"

        This is probably because of what is known as "Betfairs X-Matching Bot'". which generates synthetic odds for the web page but not the API.
        See This thread for more info.


        Rui Rodrigues

        "NullReferenceException was unhandled - Object reference not set to an instance of an object"
        Have you completed upto step 73 ?
        because the null reference problem is caused by not redirecting MenuTree.usrmsg

        have a look at step 73, your form1.cs constructor should contain the redirection code
        Code:
        c_MenuTree.MsgRedirect( this.UsrMsg );
        I'm less certain, but this may also be the cause of your lock( e_mData.varsLock ) problem.


        Drifter and AzureGulf, thanks for the feedback and encouragement makes me feel I'm not wasting my time and I'll carry on.

        part 7 hopefully end of this week or early next week.

        Comment

        • Drifter
          Junior Member
          • Mar 2009
          • 30

          #34
          You kidding?

          No, seriously. I have a bot up and running already, but my background in scripting and C really doesn't help me when it comes to Object oriented methods. The 'subscriber' model you are using is the sort of thing I would like to be able to get to myself but really struggle. I don't deny there are odd things I might do differently - but that isn't the point. Your development isn't helping me access Betfair (I already do that) or even teaching me to program (likewise). But it is helping me use the API much better than I could do with my existing skillset. I also think it is very useful to have a C# model next to the VB one on the other thread. Structured methods are only lightly addressed over there and as for threading, events, delegates, OO design principles...


          Keep up the good work.

          PS - I'm also interested in seeing a database access strategy (whether persistent or not) and a way of addressing and passing market information on multiple EventID's to multiple separate client forms - if it fits in with your approach, and of course if you have the time and interest! Your posts so far have already enhanced my appreciation of what C#/.Net brings me, and I look forward to more of the same!
          Last edited by Drifter; 18-07-2012, 12:07 AM.

          Comment

          • fravenda
            Junior Member
            • May 2012
            • 4

            #35
            hello

            first of all congratulations on the excellent work I had a question in step 14. I can make the button, only I have a question regarding the click event. I would appreciate if they could help.

            ps1: Again congratulations on the excellent work

            ps2: I'm still a beginner in programming.

            greetings

            Comment

            • Escapee
              Junior Member
              • Feb 2009
              • 51

              #36
              Howto add a Button OnClick event

              fravenda

              as a beginer, I understand it can seem hard and daunting at first even to understand the basics of things like adding an event to a form.

              but keep trying and with just a little practice it will become much easier.

              Try some smaller beginers examples like this Create a webbrowser step by step from Microsoft and you'll soon be upto speed.

              Here is step 14 illustrated, how to add the button onclick event.

              Comment

              • Escapee
                Junior Member
                • Feb 2009
                • 51

                #37
                Drifter,
                I also had a learning curve to overcome when I transitioned from many years using procedural based languages such as 'C' to OO so I understand some of the brain ache you will be experiencing.

                "I'm also interested in seeing a database access strategy"
                I've only written a few PC programs that utilise databases ( although I've done alot of C/UNIX/ORACLE stuff ) so I'm probably not the best to be giving advice on it yet.

                and a way of addressing and passing market information on multiple EventID's to multiple separate client forms
                I've done a few Football programs which accessed multiple markets concurrently and pretty much just extended the architecture utilised in this simple example. Either by using arrays of mData[] structures attatched to a fixture object/control or as per strict OO methodology encapsulating each mData and associated refresh thread/control into its own object.

                It all depends on what you want to achieve. When designing a new program you'll often find that visualising the whole design is difficult or impossible because the final target is moving and uncertain. so try visualising the data as something you can relate to and work from there.
                i.e. in this example, think of the data as a noticeboard, with in this case one program refreshing the noticeboard every second but you may have more than one refresher to a single board. and then many programs or functions reading the noticeboard independently. so with " multiple EventID's to multiple separate client forms" could you do it with just a larger noticeboard, or multiple completely independent noticeboards, or a noticeboard pointing to multiple sub noticeboards, ete etc.
                Once you can visualise the data, then you can start thinking about how to create and refresh it, then access and act upon it.

                Hope this helps, probably explained badly.
                Last edited by Escapee; 18-07-2012, 04:53 PM.

                Comment

                • fravenda
                  Junior Member
                  • May 2012
                  • 4

                  #38
                  Escapee

                  Thank you so much Escapee. already made ​​it through step 14 and go on their way to the fourth part. Only the following error occurred at the end of part 3, which says: "The name c_MenuTree does not exist in the current context." This error is in Form1.cs. where I went wrong?

                  and thanks for the tutorial. I will deepen the knowledge

                  Greetings

                  Comment

                  • Escapee
                    Junior Member
                    • Feb 2009
                    • 51

                    #39
                    fravenda
                    "The name c_MenuTree does not exist in the current context."

                    Have alook at step 38, you probably forgot to rename the MenuTree control from its default ( "MenuTree1" I think ) to c_MenuTree.

                    you can rename it now by going to the Form1 designer ( i.e. the bit where you add controls to the form ) click on the MenuTree you have on the form already and this should show its 'properties' window.
                    change its Name property to 'c_MenuTree'

                    Comment

                    • fravenda
                      Junior Member
                      • May 2012
                      • 4

                      #40
                      Escapee

                      you are great Escapee. the problem was in step 38 as you said ... mistakes of a beginner. now I have a question regarding the step 43. I do not see where to put the code?! do not know if you noticed but I'm not English and so I had some problems with the logic and language. nothing to make the google translator to break

                      Comment

                      • fravenda
                        Junior Member
                        • May 2012
                        • 4

                        #41
                        Escapee

                        problem solved ... thanks anyway

                        Comment

                        • Drifter
                          Junior Member
                          • Mar 2009
                          • 30

                          #42
                          I also had a learning curve to overcome when I transitioned from many years using procedural based languages such as 'C' to OO so I understand some of the brain ache you will be experiencing.
                          previous mail was written late at night under the affluence of incohol. It does read rather like a desparate plea!

                          Having written a bot(s) that polls for data and then process it in a traditional waterfall type strategy, there is obvious latency and some code awkwardness. A small amount of reading on some of the O-O design patterns makes painfully clear that there are many better ways to do it. The problem is to bootstrap ones-self to a degree of fluency in order to be able to code without really understanding how the patterns translate.

                          As it stands, a football bot I wrote does its job quite well - it manages (say) all the premiership markets at once but essentially sequentially. I don't want to stand still on the design side though and would like to be able to understand the application of the design strategies I perceive as being useful here. But I am not a code-monkey by trade, so it is an uphill struggle.

                          Clearly things like subscription models, multiple clients and persistent state objects are the things I feel I want to get a grip on and so see me trying to develop my bot along those lines. It currently does all those things - just not in a way I see as being remotely optimal. Threading, events and delegates are uppermost in my thoughts as things to master, as I can see the specific applications. While I have 'a clue' seeing a full worked example somehow makes it easier to see how to carry it forward.
                          Last edited by Drifter; 18-07-2012, 08:55 PM.

                          Comment

                          • didacus
                            Junior Member
                            • Jul 2012
                            • 2

                            #43
                            Thank you Escapee for excellent work!

                            Comment

                            • Escapee
                              Junior Member
                              • Feb 2009
                              • 51

                              #44
                              Nice one didacus


                              Part 7
                              The Market Display Control ( a.k.a the Market Grid )


                              In this part we are going to create a control that displays the
                              Market runners and prices.
                              It features Customising the DataGridView Control class and Overriding Paint()
                              to enhance the display




                              The runners and prices info is really just a bunch of data that should
                              be displayed to the user in a table ( tabular ) format, and there are various
                              standard controls in visual studio which can be used and customised for this
                              purpose.
                              In this example we are going to utilise the "DataGridView" control (DGV) which is pretty much a bare bones skeleton Excel clone.


                              The DGV is a flexible platform from which to manage and display all sorts of data, but
                              this flexibility does come at a cost to simplicity at times.
                              It also comes with an extensive design interface, which although a bit fiddly in places,
                              enables a lot of the settings and customisation to be specified thru the designer rather
                              than thru code.
                              But as specifying in text the steps required to create our custom grid via the designer
                              would need a lot of pictures and imagination, I'm going to do it all in code.

                              A standard Cell in the DGV would typically display one value or control, but in this
                              example, we would really Like to display the ODDS & AMMOUNT Avaiable in the same Cell.
                              So I'm going to do that by creating a custom cell and overriding the standard 'Paint' function.

                              We're just going to add extra text with a different font, but there are all sorts of draw functions
                              avalable in the graphic library and we could draw a chart or what ever from the Paint routine.
                              Once you get comfortable with overriding Paint on your custom controls you can really make your gui boogie.

                              The flexability and complexity of DGV is so vast that I couldn't cover 1% of it in this tutorial. The code
                              below is just one of many ways of customising it, and it probably contains a few "Could do that better"
                              moments.

                              Step 75
                              Right Click BetfairControls, ADD->UserControl... rename it to MarketGrid.... ->ADD.
                              Step 75a
                              in MarketGrid.Designer.cs, Comment out the AutoScaleMode

                              Step 76
                              in MarketGrid.cs, change UserControl to DataGridView like this:
                              Code:
                              namespace BetfairControls
                              {
                                  public partial class MarketGrid : [COLOR="Red"]DataGridView[/COLOR]
                                  {
                                      public MarketGrid()
                                      {
                                          InitializeComponent();
                                      }
                                  }
                              }
                              Step 77
                              Add this to below the existing using statements
                              Code:
                              using System.Diagnostics;
                              
                              using BetfairAPI;
                              Then add the Standard UsrMsg Code, copy it from CMarketData.cs ( see step 55 for more info )

                              Save and compile to check its all ok.




                              We now need a custom Cell class and ( for ease of use but not absolutely required) a custom column class.
                              Strict OO encapsulation methodology rules that these should be seperate entities in seperate files, but hey ho, I just stick
                              the code for them in the same file as the DGV, makes life easier.

                              Step 78
                              Below the MarketGrid class, add the OddsCell class, like this:
                              Code:
                              namespace BetfairControls
                              {
                                  public partial class MarketGrid : DataGridView
                                  {
                                      public MarketGrid()
                                      {
                                          InitializeComponent();
                                      }
                                  }
                                  
                              [COLOR="SeaGreen"]    //
                                  // OddsColumn Class Code should replace this comment
                                  //[/COLOR]
                              
                                  public class OddsCell : DataGridViewTextBoxCell
                                  {
                                      public OddsCell()
                                      {
                                          dOdds = 0;
                                          dStake = 0;
                                      }
                                      public double dOdds;
                                      public double dStake;
                              
                                      private OddsColumn parent = null;
                              
                                      Color TxtColor = Color.Black;
                              
                                      public override object Clone()
                                      {
                                          OddsCell c =  base.Clone() as OddsCell;
                              
                                          return c;
                                      }
                              
                                      protected override void Paint( Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts )
                                      {
                                          base.Paint( graphics, clipBounds, cellBounds, rowIndex, cellState, value, "", errorText, cellStyle, advancedBorderStyle, paintParts );
                              
                                          string sOdds = " ";
                                          string sStake = " ";
                              
                                          if( dOdds > 1 )
                                          {
                                              sOdds = dOdds.ToString();
                                              sStake = dStake.ToString( "£#" );
                                          }
                              
                                          if( parent == null )
                                          {
                                              parent = (OddsColumn)this.OwningColumn;
                                          }
                              
                                          SizeF sizeOdds = graphics.MeasureString( sOdds, parent.fontOdds );
                                          SizeF sizeStake = graphics.MeasureString( sStake, parent.fontStake );
                              
                                          PointF pointO = new PointF( ( cellBounds.Width - sizeOdds.Width ) / 2, 4 );
                                          PointF pointS = new PointF( ( cellBounds.Width - sizeStake.Width ) / 2, 25 );
                              
                                          using( SolidBrush brush = new SolidBrush( TxtColor ) )
                                          {
                                              graphics.DrawString( sOdds, parent.fontOdds, brush,
                                                  cellBounds.X + pointO.X,
                                                  cellBounds.Y + pointO.Y );
                              
                                              graphics.DrawString( sStake, parent.fontStake, brush,
                                                  cellBounds.X + pointS.X,
                                                  cellBounds.Y + pointS.Y );
                                          }
                                      
                                      }
                                  }
                              
                              }
                              Lets go thru the Cell code and explain it a bit.

                              public class OddsCell : DataGridViewTextBoxCell
                              We're inheriting from the standard Text Cell. there are about 5 standard types such as button, combobox etc

                              Then we have the constructor and our the variables which we are using to store the Odds and Stake etc.
                              pretty standard stuff.

                              The non-standard stuff is:

                              public override object Clone()
                              {
                              OddsCell c = base.Clone() as OddsCell;

                              return c;
                              }

                              For reasons I've forgotten, Customised Cells need to override the Clone() function to enable DGV
                              to manage them properly. I'll often stick some other pre-cell-creation code in here.

                              And then we get to protected override void Paint( Graphics graphics, Rect......

                              As you can see "Paint()" has zillions of parameters, and I suspect might take a year or two to master fully.
                              But alot can still be achieved in a state of ignorance. I'll briefly mention a few of the things worth noting
                              as a novice.

                              a) To overcome all the issues raised by differing devices, screen sizes, resolution etc etc, Paint() ignores
                              the problem and its job is just to paint on a "graphics" object, Letting these issues be handled elsewhere.

                              b) To draw or place text on a control, use the grahics object passed as a parameter to paint().
                              i.e. graphics.DrawString(....) or graphics.DrawRectancle(....) etc etc

                              c) Paint can be called multiple times for each control. To draw the background, then borders etc etc. To discern
                              exactly what a individual call is tasked with you can examine the "paintParts" parameter.
                              ( I think the DGV Cell.Paint() is called only once per cell with paintParts=All but I could be wrong )

                              d) It is generally good practice to first call base.Paint() when overriding paint as most times you'll want to just
                              paint over a standard control ( Cell in this case )

                              Now to the specifics of our Paint() Override:

                              You will see that as per d) I have called base.paint(), but because in our cusomisation we don't use the standard
                              cell.value I have substituted the formattedValue parameter with "" in the base.Paint() call

                              base.Paint( graphics, clipBounds, cellBounds, rowIndex, cellState, value, "", errorText, cellStyle, advancedBorderStyle, paintParts );

                              Then we have some Strings to hold the text we want to draw

                              string sOdds = " ";
                              string sStake = " ";


                              if( dOdds > 1 )
                              {
                              sOdds = dOdds.ToString();
                              sStake = dStake.ToString( "£#" );
                              }


                              Next we check and set the cell parent.
                              Because we are drawing text in multiple fonts, we need some font objects. We could easily create some new objects
                              at this point but as Paint() gets called ALOT of times, repeatedly creating and disposing of objects can have
                              an impact on performance, so I break the OO encapsulation rules and create them ( the fonts ) at a higher level to avoid repeated creation/destruction.
                              Therefore to access them we need to have a pointer to the parent of this object ( Cell ).
                              if( parent == null )
                              {
                              parent = (OddsColumn)this.OwningColumn;
                              }


                              To place our text neatly in the middle of the cell we need to measure how big the text will be when using
                              the specified font.
                              SizeF sizeOdds = graphics.MeasureString( sOdds, parent.fontOdds );
                              SizeF sizeStake = graphics.MeasureString( sStake, parent.fontStake );


                              Now we know how wide the text is we can calculate the upper left points on the cell surface where
                              we will start drawing the text.
                              PointF pointO = new PointF( ( cellBounds.Width - sizeOdds.Width ) / 2, 4 );
                              PointF pointS = new PointF( ( cellBounds.Width - sizeStake.Width ) / 2, 25 );

                              I have hard coded the 'y' (height) parameters as 4 and 25 but these could be calculated as well.

                              So now we have all the things required to draw the text, we'll just go ahead and draw it.
                              using( SolidBrush brush = new SolidBrush( TxtColor ) )
                              {
                              graphics.DrawString( sOdds, parent.fontOdds, brush,
                              cellBounds.X + pointO.X,
                              cellBounds.Y + pointO.Y );

                              graphics.DrawString( sStake, parent.fontStake, brush,
                              cellBounds.X + pointS.X,
                              cellBounds.Y + pointS.Y );
                              }


                              And that is how you override Paint() simples.....





                              Now we have our custom cell to display the Odds and Ammount, we create a custom column for our OddsCell,
                              As I mentioned earlier, it can be done with out this but it make it easier with it. A columns doesn't
                              need to be made of all the same cell types, you can make any cell in the grid take on the persona of
                              any cell type you want, but when a column is all or even mostly the same cell type then its easier to
                              work with a custom column.

                              Step 79
                              Insert the OddsColumn class code above the OddsCell class code ( see comment in step 78 code )
                              Code:
                                  public class OddsColumn : DataGridViewColumn
                                  {
                                      public OddsColumn()
                                      {
                                          this.CellTemplate = new OddsCell();
                                          this.ReadOnly = true;
                                      }
                                      public Font fontOdds;
                                      public Font fontStake;
                              
                              
                                      public override object Clone()
                                      {
                              
                                          OddsColumn col = base.Clone() as OddsColumn;
                              
                                          col.fontOdds = fontOdds;
                                          col.fontStake = fontStake;
                              
                                          return col;
                                      }
                                  }
                              Brief Explanation of OddsColumns Code:

                              It inherits from a standard column
                              public class OddsColumn : DataGridViewColumn

                              In the constructor we set the default cell template for cells in this column as that of our customised OddsCell
                              this.CellTemplate = new OddsCell();

                              Then the Fonts that are needed in the custom cells
                              public Font fontOdds;
                              public Font fontStake;


                              And as per a custom cell, we also need to override the Clone() function.
                              public override object Clone()
                              {
                              OddsColumn col = base.Clone() as OddsColumn;

                              col.fontOdds = fontOdds;
                              col.fontStake = fontStake;

                              return col;
                              }


                              So thats our custom cell and column, we can now move on to customising the DGV itself.

                              Step 80
                              Back in the MarketGrid class change the constructor to look like this.

                              Code:
                                      public MarketGrid()
                                      {
                                          InitializeComponent();
                              
                              
                                          AllowUserToAddRows = false;
                                          AllowUserToDeleteRows = false;
                                          AllowUserToOrderColumns = false;
                                          AllowUserToResizeColumns = false;
                                          AllowUserToResizeRows = false;
                                          CellBorderStyle = DataGridViewCellBorderStyle.Raised;
                                          ColumnHeadersVisible = false;
                                          DoubleBuffered = true;
                                          EditMode = DataGridViewEditMode.EditProgrammatically;
                                          MultiSelect = false;
                                          ReadOnly = true;
                                          RowHeadersVisible = false;
                                          RowTemplate.Height = 40;
                                          SelectionMode = DataGridViewSelectionMode.CellSelect;
                              
                              
                                          fontOdds = new Font( FontFamily.GenericSansSerif, 11.25F, FontStyle.Bold );
                                          fontStake = new Font( FontFamily.GenericSansSerif, 8.25F,FontStyle.Regular );
                                          fontName = new Font( FontFamily.GenericSansSerif, 8.25F, FontStyle.Bold );
                              
                                          this.SelectionChanged += new System.EventHandler( this.OnSelectionChanged );
                                      }
                              I'm setting some of the multitude of DataGridView properties using code in this constructor, but most of
                              this can be done using the designer instead. Experiment with it some time.

                              Step 81
                              Below the UsrMsg code, add these variables
                              Code:
                                      public CMarketData e_mData;
                              
                                      public Font fontOdds;
                                      public Font fontStake;
                                      public Font fontName;
                              
                                      public Color clrBack = Color.FromArgb( 200, 208, 228 );
                                      public Color clrLay = Color.FromArgb( 228, 184, 214 );
                              
                                      public volatile object GridLock = new object();

                              Step 82
                              Next add the InitGrid() function.
                              This creates the columns on the grid at runtime, but it is often easier to do the
                              bulk of this from within the designer at designtime. I'm doing it this way because
                              its easier to communicate it to you.

                              Code:
                                      public void InitGrid()
                                      {
                                          TTraceMsg( "==============================INITGRID()\n" );
                              
                                          int c;
                                          int o;
                              
                                          DataGridViewColumn[] Col = new DataGridViewColumn[8];
                              
                              
                              
                                          Rows.Clear();
                                          Columns.Clear();
                              
                              
                                          c = 0;
                                          Col[c] = new DataGridViewTextBoxColumn();
                                          Col[c].Name = "ColName";
                              
                                          Col[c].DefaultCellStyle.Font = fontName;
                                          Col[c].HeaderText = Col[c].Name;
                                          Col[c].ReadOnly = true;
                                          Col[c].Resizable = DataGridViewTriState.False;
                                          Col[c].SortMode = DataGridViewColumnSortMode.NotSortable;
                                          Col[c].MinimumWidth = 100;
                                          Col[c].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                                          Col[c].FillWeight = 33;
                              
                                          Columns.Add( Col[c] );
                              
                                          o = 3;
                                          for( c = 1; c <= 3; c++ )
                                          {
                                              Col[c] = new OddsColumn();
                                              Col[c].Name = string.Format( "BackOdds{0}", o-- ); ;
                              
                                              Col[c].HeaderText = Col[c].Name;
                                              Col[c].ReadOnly = true;
                                              Col[c].Resizable = DataGridViewTriState.False;
                                              Col[c].SortMode = DataGridViewColumnSortMode.NotSortable;
                                              Col[c].MinimumWidth = 40;
                                              Col[c].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                                              Col[c].FillWeight = 11;
                                              Col[c].DefaultCellStyle.BackColor = clrBack;
                                              
                                              ( (OddsColumn)Col[c] ).fontOdds = fontOdds;
                                              ( (OddsColumn)Col[c] ).fontStake = fontStake;
                              
                              
                              
                                              Columns.Add( Col[c] );
                                          }
                              
                                          c = 4;
                                          Col[c] = new DataGridViewTextBoxColumn();
                                          Col[c].Name = "ColMid";
                              
                                          Col[c].HeaderText = Col[c].Name;
                                          Col[c].ReadOnly = true;
                                          Col[c].Resizable = DataGridViewTriState.False;
                                          Col[c].SortMode = DataGridViewColumnSortMode.NotSortable;
                                          Col[c].MinimumWidth = 5;
                                          Col[c].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                                          Col[c].FillWeight = 1;
                              
                                          Columns.Add( Col[c] );
                              
                                          o = 1;
                                          for( c = 5; c <= 7; c++ )
                                          {
                                              Col[c] = new OddsColumn();
                                              Col[c].Name = string.Format( "LayOdds{0}", o++ );
                              
                                              Col[c].HeaderText = Col[c].Name;
                                              Col[c].ReadOnly = true;
                                              Col[c].Resizable = DataGridViewTriState.False;
                                              Col[c].SortMode = DataGridViewColumnSortMode.NotSortable;
                                              Col[c].MinimumWidth = 40;
                                              Col[c].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                                              Col[c].FillWeight = 11;
                                              Col[c].DefaultCellStyle.BackColor = clrLay;
                              
                                              ( (OddsColumn)Col[c] ).fontOdds = fontOdds;
                                              ( (OddsColumn)Col[c] ).fontStake = fontStake;
                              
                                              Columns.Add( Col[c] );
                              
                                          }
                              
                              
                                      }
                              A small note: It would seem sensible to have InitGrid() totally encapsulated within MarketGrid and just
                              call InitGrid() from the constructor. But because of the way the Visual studio designer interacts with the constuctor
                              of controls, this leads to duplication of columns. ( a bug ? )
                              As a kludge round this issue I call InitGrid() from the form, it may not be the best or most elegant solution
                              but it works and I couldn't be bothered to navigate Microsoft documentation to see if they had fixed it.

                              Sometimes you will find not all Microsoft code is user friendly



                              Part 7 Continues next post.........
                              Last edited by Escapee; 22-07-2012, 01:05 PM.

                              Comment

                              • Escapee
                                Junior Member
                                • Feb 2009
                                • 51

                                #45
                                Part 7 Continued.....

                                Our Market Grid will respond to 2 events
                                1) NewMarket, when it'll just clear all the previous market rows from the grid and create new ones
                                for the new market
                                2) MarketUpdated, Its main Job. The market data has just been refreshed, so it need to display the
                                new data.

                                Step 83
                                Add the events functions
                                Code:
                                        public delegate void dlgOnNewMarket( object sender, EventArgs e );
                                        public void OnNewMarket( object sender, EventArgs e )
                                        {
                                            if( InvokeRequired )
                                            {
                                                BeginInvoke( new dlgOnMarketUpdated( OnNewMarket ), new object[] { sender, e } );
                                                return;
                                            }
                                
                                            lock( GridLock )
                                            {
                                                Rows.Clear();
                                
                                                if( e_mData.nRunners < 1 )
                                                {
                                                    return;
                                                }
                                
                                                for( int r = 0; r < e_mData.nRunners; r++ )
                                                {
                                                    Rows.Add( e_mData.RDATA[r].Name );
                                                }
                                
                                                
                                            }
                                
                                        }
                                Code:
                                public delegate void dlgOnMarketUpdated( object sender, EventArgs e );
                                        public void OnMarketUpdated( object sender, EventArgs e )
                                        {
                                            if( InvokeRequired )
                                            {
                                                BeginInvoke( new dlgOnMarketUpdated( OnMarketUpdated ), new object[] { sender, e } );
                                                return;
                                            }
                                
                                
                                            int r;
                                            int bestBackCol = 3;
                                            int bestLayCol = 5;
                                
                                            lock( GridLock )
                                            {
                                
                                                r = 0;
                                                foreach( DataGridViewRow  rw in this.Rows )
                                                {
                                                    if( e_mData.RDATA[r].BackPrice[0].dOdds > 1 )
                                                    {
                                                        ( (OddsCell)rw.Cells[bestBackCol] ).dOdds = e_mData.RDATA[r].BackPrice[0].dOdds;
                                                        ( (OddsCell)rw.Cells[bestBackCol] ).dStake = e_mData.RDATA[r].BackPrice[0].dAmount;
                                                    }
                                                    else
                                                    {
                                                        ( (OddsCell)rw.Cells[bestBackCol] ).dOdds = -1;
                                                        ( (OddsCell)rw.Cells[bestBackCol] ).dStake = -1;
                                                    }
                                                    if( e_mData.RDATA[r].BackPrice[1].dOdds > 1 )
                                                    {
                                                        ( (OddsCell)rw.Cells[bestBackCol - 1] ).dOdds = e_mData.RDATA[r].BackPrice[1].dOdds;
                                                        ( (OddsCell)rw.Cells[bestBackCol - 1] ).dStake = e_mData.RDATA[r].BackPrice[1].dAmount;
                                                    }
                                                    else
                                                    {
                                                        ( (OddsCell)rw.Cells[bestBackCol - 1] ).dOdds = -1;
                                                        ( (OddsCell)rw.Cells[bestBackCol - 1] ).dStake = -1;
                                                    }
                                                    if( e_mData.RDATA[r].BackPrice[2].dOdds > 1 )
                                                    {
                                                        ( (OddsCell)rw.Cells[bestBackCol - 2] ).dOdds = e_mData.RDATA[r].BackPrice[2].dOdds;
                                                        ( (OddsCell)rw.Cells[bestBackCol - 2] ).dStake = e_mData.RDATA[r].BackPrice[2].dAmount;
                                                    }
                                                    else
                                                    {
                                                        ( (OddsCell)rw.Cells[bestBackCol - 2] ).dOdds = -1;
                                                        ( (OddsCell)rw.Cells[bestBackCol - 2] ).dStake = -1;
                                                    }
                                
                                
                                
                                
                                                    if( e_mData.RDATA[r].LayPrice[0].dOdds > 1 )
                                                    {
                                                        ( (OddsCell)rw.Cells[bestLayCol] ).dOdds = e_mData.RDATA[r].LayPrice[0].dOdds;
                                                        ( (OddsCell)rw.Cells[bestLayCol] ).dStake = e_mData.RDATA[r].LayPrice[0].dAmount;
                                                    }
                                                    else
                                                    {
                                                        ( (OddsCell)rw.Cells[bestLayCol] ).dOdds = -1;
                                                        ( (OddsCell)rw.Cells[bestLayCol] ).dStake = -1;
                                                    }
                                                    if( e_mData.RDATA[r].LayPrice[1].dOdds > 1 )
                                                    {
                                                        ( (OddsCell)rw.Cells[bestLayCol + 1] ).dOdds = e_mData.RDATA[r].LayPrice[1].dOdds;
                                                        ( (OddsCell)rw.Cells[bestLayCol + 1] ).dStake = e_mData.RDATA[r].LayPrice[1].dAmount;
                                                    }
                                                    else
                                                    {
                                                        ( (OddsCell)rw.Cells[bestLayCol + 1] ).dOdds = -1;
                                                        ( (OddsCell)rw.Cells[bestLayCol + 1] ).dStake = -1;
                                                    }
                                                    if( e_mData.RDATA[r].LayPrice[2].dOdds > 1 )
                                                    {
                                                        ( (OddsCell)rw.Cells[bestLayCol + 2] ).dOdds = e_mData.RDATA[r].LayPrice[2].dOdds;
                                                        ( (OddsCell)rw.Cells[bestLayCol + 2] ).dStake = e_mData.RDATA[r].LayPrice[2].dAmount;
                                                    }
                                                    else
                                                    {
                                                        ( (OddsCell)rw.Cells[bestLayCol + 2] ).dOdds = -1;
                                                        ( (OddsCell)rw.Cells[bestLayCol + 2] ).dStake = -1;
                                                    }
                                
                                                    r++;
                                                }
                                            }
                                            Refresh();
                                        }
                                
                                        private void OnSelectionChanged( object sender, EventArgs e )
                                        {
                                            if( SelectedCells.Count > 0 )
                                            {
                                                SelectedCells[0].Selected = false;
                                            }
                                        }
                                Save and compile to check you haven't missed anything.


                                There it is, a custom control for displaying the market data, all that is needed now
                                is to create one on our form and hook up the events to the event publishers.


                                Step 84
                                in the Form1 designer, enlarge the form so that it has room to display the market.
                                You should be able to see our custom 'MarketGrid' in the 'BetfairControls' Components tool box.
                                Create a MarketGrid control on form1 with the following properties:

                                Name=c_MarketGrid
                                Anchor=Top,Bottom,Left,Right

                                (all the other properties are coded in the constructor)

                                and you should have something like this



                                Step 85
                                In the Form1.cs file, change the Form1() constructor so it looks like this
                                Code:
                                        public Form1()
                                        {
                                            InitializeComponent();
                                
                                            MyBetfair = new CBetfairAPI();
                                            MyBetfair.MsgRedirect( this.UsrMsg );
                                
                                            mData = new CMarketData();
                                            mData.MsgRedirect( this.UsrMsg );
                                
                                            c_MenuTree.e_Betfair = MyBetfair;
                                            c_MenuTree.e_mData = mData;
                                            c_MenuTree.evNewMarket += new BetfairControls.MenuTree.NewMarketHandler( c_MktGrid.OnNewMarket );
                                            c_MenuTree.evNewMarket += new BetfairControls.MenuTree.NewMarketHandler( this.OnNewMarket );
                                            c_MenuTree.MsgRedirect( this.UsrMsg );
                                
                                            c_Refresh.e_mData = mData;
                                            c_Refresh.evMarketUpdated += new BetfairControls.RefreshControl.MarketUpdatedHandler( c_MktGrid.OnMarketUpdated );
                                            c_Refresh.evMarketUpdated += new BetfairControls.RefreshControl.MarketUpdatedHandler( this.OnMarketUpdated );
                                            c_Refresh.MsgRedirect( this.UsrMsg );
                                
                                            c_MktGrid.e_mData = mData;
                                            c_MktGrid.MsgRedirect( this.UsrMsg );
                                            c_MktGrid.InitGrid();
                                
                                            eLastUpdate.BorderStyle = BorderStyle.None;
                                            eMktDesc.BorderStyle = BorderStyle.None;
                                
                                            bLoggedOn = false;
                                
                                
                                        }
                                Save, Compile and RUN.....

                                and you should have this to play with.


                                "Houston we have cleared the tower."
                                Last edited by Escapee; 22-07-2012, 01:19 PM.

                                Comment

                                Working...
                                X