C# a Step by Step Beginners Tutorial

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts

  • Rui Rodrigues
    replied
    Escapee, thank you so very much for what you´ve done so far. Hope you won´t leave us hanging

    Got everything working just fine and now will study and explore possibilities. Have one question though (so far), sometimes I get prices like 42 and the real price is 4.2 but other times all is fine, what could be the problem? decompressing prices? parsing the markets string?

    thanks in advance.

    Leave a comment:


  • Rui Rodrigues
    replied
    Originally posted by Escapee View Post


    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.

    Sorry for not replying sooner. Have been stuck in the Hospital for a few days with high fevers Now I'm back.

    Thank you. Yep the problem was not having completed a few more steps in advance, that solved part of it. And had to add "using BetfairAPI.BFExchange" to CMarketData.cs

    All working now!

    Now I'll try to catch up with you guys.

    Leave a comment:


  • Escapee
    replied
    didacus will you continue with your tutorial?


    I'm not sure, it takes up many hours of 'free' time to write it.

    the next logical step would be to write the "My Bets" module and that would take a couple of days coding and probably a day or two to write into a tutorial.
    Not sure I can spare that sort of time at the moment.


    I don't mind answering questions but I think the Bets Module will have to wait at least a few weeks.

    Leave a comment:


  • didacus
    replied
    I am very interested, will you continue with your tutorial?
    Thank you

    Leave a comment:


  • Escapee
    replied
    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.

    Leave a comment:


  • Escapee
    replied
    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.

    Leave a comment:


  • didacus
    replied
    Thank you Escapee for excellent work!

    Leave a comment:


  • Drifter
    replied
    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.

    Leave a comment:


  • fravenda
    replied
    Escapee

    problem solved ... thanks anyway

    Leave a comment:


  • fravenda
    replied
    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

    Leave a comment:


  • Escapee
    replied
    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'

    Leave a comment:


  • fravenda
    replied
    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

    Leave a comment:


  • Escapee
    replied
    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.

    Leave a comment:


  • Escapee
    replied
    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.

    Leave a comment:


  • fravenda
    replied
    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

    Leave a comment:

Working...
X