C# a Step by Step Beginners Tutorial

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

  • Escapee
    replied
    AzureGulf:
    By the way, when you're building your MenuTree, you might like to sort the Events/Markets using code a bit like this:
    Thats a good way of doing it. I kind of forget that C# comes with LINQ built in and don't often use it.
    In the past I have just written custom callback functions for MenuTree sorting but thinking about it your method would do 80% of the time.

    Leave a comment:


  • AlgoTrader
    replied
    Originally posted by Drifter View Post
    Compression is used because the free API allows 60 calls per minute to the compressed functions, but only 10 to the raw versions.
    Compression is usually mentioned related to gzip HTTP compression. calls like getAllMarkets can contain hundreds of kilobytes and be quite slow to receive data. GZIP compressiom reduce network traffic in 10 times, it will be just dozens of kilobytes to be transmitted. The latency drops drastically.

    Another thing that drops latency is persistent connections. It takes 15ms to call getAlllMarketPricesCompressed when I use already established connection and 90ms when there is no ready connection.

    Ignoring those issues makes the bot an underdog

    Leave a comment:


  • Drifter
    replied
    Compression is used because the free API allows 60 calls per minute to the compressed functions, but only 10 to the raw versions.

    The 5* thing may have been me - I didn't realise it was global. I have such power...

    Leave a comment:


  • AzureGulf
    replied
    Compression Flag and sorting MenuTree

    Escapee - I think you're correct in setting DeCompression to true in order to enable compression, from what I've seen in the VB2008 thread (by Mumbles0) in this forum...

    By the way, when you're building your MenuTree, you might like to sort the Events/Markets using code a bit like this:

    Code:
                                    var sortedEvents = from events in response.eventItems
                                                 orderby events.menuLevel, events.eventName
                                                 select events;
    
                                    foreach (BFEvent bfEvent in sortedEvents)
                                    {
                                      ... add to menu tree as per your example...
                                    }
    Needless to say, the same can be done for the market items in the next block of code...you might like to check the correct sort order, so that markets don't become disassociated from their relevant events!

    Looking forward to your next post

    Leave a comment:


  • Escapee
    replied
    Thanks for the encouragement and thanks to who ever rated this thread 5 stars.

    I'm all booked up for the next week/10 days but I will try and add some more as time permits.

    Azure Gulf:
    If you have a moment, please explain why you've set "EnableDecompression to true "
    I was under the impression this is how gzip compression/decompression was enabled, but I can't readily find the documentation I read to make me think that so I'll look into it again and let you know.

    Leave a comment:


  • AzureGulf
    replied
    Hi Escapee - I'm following this thread and hope you'll continue - so far, it's been very helpful.

    If you have a moment, please explain why you've set "EnableDecompression to true " for both services - as I understand it, the Betfair API can also send compressed data which is quicker and permits a higher call rate to the service. I'm just wondering if this should be set to false to take advantage of this??

    Many thanks...

    Leave a comment:


  • Drifter
    replied
    I think this is a brilliant idea. I would like to see it continued if you have the patience. Once thing I never quite worked out is how the asynchronous calls worked in C#. Also, if you have the time threading and database access would be great additions. My idea was to create a general bet management class for monitoring bet status using threads and appropriate callbacks (I tried to use the Ami Thread module SmartThreadPool, but it was simply beyond me!)
    Last edited by Drifter; 07-06-2012, 08:52 PM.

    Leave a comment:


  • Escapee
    replied
    I have now Added Part 3 of this tutorial into posts No 5 & 6 of this thread.

    After completing Part 3 you should have this to play about with




    The Complete Code so far could not fit into those posts so I have put it in this one below:

    Form1.cs
    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    using System.Diagnostics;
    using BetfairAPI;
    
    namespace TestForm1
    {
        public partial class Form1 : Form
        {
            public CBetfairAPI MyBetfair;
            public bool bLoggedOn;
    
            public Form1()
            {
                InitializeComponent();
    
                MyBetfair = new CBetfairAPI();
    
                c_MenuTree.m_Betfair = MyBetfair;
    
                bLoggedOn = false;
            }
    
            private void ButLogOn_Click( object sender, EventArgs e )
            {
                string uuu = "YourUserName";
                string ppp = "YourPassword"; 
    
    
                if( bLoggedOn == false )
                {
                    if( MyBetfair.Login( uuu, ppp ) == true )
                    {
                        bLoggedOn = true;
    
                        c_MenuTree.Initialise();
    
                        ButLogOn.Text = "Log Out";
                        this.Text = "Logged On To Betfair";
    
                    }
                    else
                    {
                        this.Text = "Log on FAILED, Check Debug Messages";
    
                    }
                }
                else
                {
                    if( MyBetfair.LogOut() == true )
                    {
                        bLoggedOn = false;
    
                        ButLogOn.Text = "Log On";
                        this.Text = "NOT Logged On To Betfair";
    
                    }
                    else
                    {
                        this.Text = "Log Out FAILED, Check Debug Messages";
    
                    }
                }
            }
        }
    }
    CBetfairAPI.cs
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    
    using System.Diagnostics;
    
    using BetfairAPI.BFGlobal;
    using BetfairAPI.BFExchange;
    
    namespace BetfairAPI
    {
        public class CBetfairAPI
        {
    
            #region Variables
    
            private BFGlobalService _bfGlobal;
            private BFExchangeService _bfExchange;
    
            private BFGlobal.APIRequestHeader _globReqHdr;
            private BFExchange.APIRequestHeader _exchReqHdr;
    
            private string _username;
            private string _password;
            private int _productId;
            private int _vendorSoftwareId;
            private string _sessionToken;
    
            private string _currency;
    
    
    
    
            #endregion
    
            #region Constuctor
    
            public  CBetfairAPI()
            {
                Debug.WriteLine( string.Format( "{0} - Initializing CBetfairAPI", DateTime.Now ) );
    
                _bfGlobal = new BFGlobalService();
    
                _bfGlobal.EnableDecompression = true;
    
                _bfExchange = new BFExchangeService();
    
                _bfExchange.EnableDecompression = true;
    
    
                _globReqHdr = new BFGlobal.APIRequestHeader();
                _exchReqHdr = new BFExchange.APIRequestHeader();
    
    
                _username = "";
                _password = "";
    
                _sessionToken = "";
    
                _productId = 82;
                _vendorSoftwareId = 0;
    
                _currency = "";
            }
    
            #endregion
    
    
    
            public bool Login( string UserName, string PassWord  )
            {
                bool bRetCode;
                const string serviceName = "Login";
    
                Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1}", DateTime.Now, serviceName ) );
    
                _username = UserName;
                _password = PassWord;
    
    
                var request = new LoginReq {    username = _username, 
                                                password = _password, 
                                                productId = _productId, 
                                                vendorSoftwareId = _vendorSoftwareId };
    
                LoginResp response = _bfGlobal.login( request );
    
                bRetCode = CheckResponse(   serviceName, 
                                            Convert.ToString( response.header.errorCode ),
                                            Convert.ToString( response.errorCode ), 
                                            response.header.sessionToken );
                if( bRetCode == false )
                {
                    Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1} - FAILED", DateTime.Now, serviceName ) );
                    return false;
                }
    
                _currency = response.currency;
    
                Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1} - OK", DateTime.Now, serviceName ) );
    
                return true;
            }
    
            public bool LogOut()
            {
                bool bRetCode;
                const string serviceName = "LogOut";
    
                Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1}", DateTime.Now, serviceName ) );
    
    
                var request = new LogoutReq();
    
                request.header = _globReqHdr;
    
                LogoutResp response = _bfGlobal.logout( request );
    
                bRetCode = CheckResponse(   serviceName,
                                            Convert.ToString( response.header.errorCode ),
                                            Convert.ToString( response.errorCode ),
                                            response.header.sessionToken );
    
                if( bRetCode == false )
                {
                    Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1} - FAILED", DateTime.Now, serviceName ) );
                    return false;
                }
    
                Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1} - OK", DateTime.Now, serviceName ) );
    
                return true;
    
            }
            public bool getActiveEventTypes( ref GetEventTypesResp response )
            {
                bool bRetCode;
                const string serviceName = "getActiveEventTypes";
    
                Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1}", DateTime.Now, serviceName ) );
    
    
                var request = new GetEventTypesReq();
    
                request.header = _globReqHdr;
    
                response = _bfGlobal.getActiveEventTypes( request );
    
                bRetCode = CheckResponse( serviceName,
                                            Convert.ToString( response.header.errorCode ),
                                            Convert.ToString( response.errorCode ),
                                            response.header.sessionToken );
    
                if( bRetCode == false )
                {
                    return false;
                }
    
                //
                // If you want to see what is returned from this call then 
                // uncomment the foreach loop below
                //
                //foreach (EventType et in response.eventTypeItems)
                //{
                //    Debug.WriteLine(string.Format("EventItem: ({0}), ({1})", et.name, et.id));
                //}
    
    
                return true;
    
            }
            public bool GetEvents( ref GetEventsResp response, int evtID )
            {
                bool bRetCode;
                const string serviceName = "getEvents";
    
                Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1}", DateTime.Now, serviceName ) );
    
    
                var request = new GetEventsReq();
    
                request.header = _globReqHdr;
                request.eventParentId = evtID;
    
                response = _bfGlobal.getEvents( request );
    
                bRetCode = CheckResponse( serviceName,
                                            Convert.ToString( response.header.errorCode ),
                                            Convert.ToString( response.errorCode ),
                                            response.header.sessionToken );
    
                if( bRetCode == false )
                {
                    return false;
                }
    
                return true;
            }
    
            private bool CheckResponse( string serviceName, string hdrErrCd, string respErrCd, string sessionToken )
            {
    
                if( ! string.IsNullOrEmpty( sessionToken ) )
                {
                    _sessionToken = sessionToken;
                    _globReqHdr.sessionToken = sessionToken;
                    _exchReqHdr.sessionToken = sessionToken;
                }
    
                if( hdrErrCd != "OK" )
                {
                    Debug.WriteLine( string.Format( "{0} - FAILED: Response.Header.ErrorCode = {1}", serviceName, hdrErrCd ) );
                    return ( false );
                }
                if( respErrCd != "OK" )
                {
                    Debug.WriteLine( string.Format( "{0} - FAILED: Response.ErrorCode = {1}", serviceName, respErrCd ) );
                    return ( false );
                }
    
                return ( true );
            }
    
    
            
    
        }
    }
    MenuTree.cs
    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    using System.Diagnostics;
    
    using BetfairAPI;
    using BetfairAPI.BFGlobal;
    using BetfairAPI.BFExchange;
    
    
    namespace BetfairControls
    {
        public partial class MenuTree : TreeView
        {
            public MenuTree()
            {
                InitializeComponent();
    
                m_Betfair = null;
            }
            public CBetfairAPI m_Betfair;
    
    
    
    
            public bool Initialise()
            {
                this.Nodes.Clear();
    
                if( m_Betfair == null )
                {
                    return false;
                }
    
                GetEventTypesResp Response = new GetEventTypesResp();
    
                if( m_Betfair.getActiveEventTypes( ref Response ) != true )
                {
                    Debug.WriteLine( "Error: MenuTree->Initialise()->m_Betfair.getActiveEventTypes() FAILED ( returned false )" );
                    return ( false );
                }
    
                if( Response.eventTypeItems != null )
                {
                    foreach( EventType et in Response.eventTypeItems )
                    {
                        Debug.WriteLine( string.Format( "Init-----EventItem: ({0}), ({1})", et.name, et.id ) );
    
                        MenuTreeNode tNode = new MenuTreeNode( et );
    
                        this.Nodes.Add( tNode );
                    }
    
                }
                else
                {
                    Debug.WriteLine( "MenuTree->Initialise()->m_BetfairgetActiveEventTypes() returned 0 Events ?!" );
    
                }
                return true;
            }
    
    
            override protected void OnAfterSelect( TreeViewEventArgs e )
            {
    
                MenuTreeNode tNode = (MenuTreeNode)e.Node;
    
                if( tNode.Nodes.Count == 0 )
                {
    
                    switch( tNode.m_NodeType )
                    {
                        case "bfEvent":
                        case "EventType":
    
                            GetEventsResp eventResp = new GetEventsResp();
    
                            if( m_Betfair.GetEvents( ref eventResp, tNode.m_id ) == false )
                            {
                                Debug.WriteLine( "OnAfterSelect()->GetEvents() Returned false ?!" );
                                return;
                            }
                            if( eventResp.eventItems != null )
                            {
    
                                foreach( BFEvent evt in eventResp.eventItems )
                                {
                                    Debug.WriteLine(string.Format("BFEvent: ({0}), ({1})", evt.eventName, evt.eventId));
    
                                    MenuTreeNode evtNode = new MenuTreeNode( evt );
                                    tNode.Nodes.Add( evtNode );
                                }
                            }
                            if( eventResp.marketItems != null )
                            {
                                foreach( MarketSummary mkt in eventResp.marketItems )
                                {
                                    Debug.WriteLine( string.Format( "MarketSummary: ({0}), ({1}), ", mkt.marketName, mkt.marketId ) );
    
                                    MenuTreeNode mktNode = new MenuTreeNode( mkt );
                                    tNode.Nodes.Add( mktNode );
                                }
                            }
                            tNode.Expand();
                            break;
    
    
                        case "MarketSummary":
    
                            // Market Summary Records are the end of the tree's branches
                            // When a user Clicks On a Market Summary Node, he really wants
                            // to load the market. Something we will do in a later part of
                            // This tutorial
    
                            Debug.WriteLine( string.Format( "User Clicked the Market: ({0}), ID  = ({1}), ", tNode.Text, tNode.m_id ) );
    
    
                            break;
    
                        default:
                            Debug.WriteLine( "Node = " + tNode.Text + " UNKNOWN Type = " + tNode.m_NodeType );
                            break;
                    }
    
                }
    
    
    
                base.OnAfterSelect( e );
            }
    
        }
    
    
    }
    MenuTreeNode.cs
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using System.Diagnostics;
    using BetfairAPI;
    using BetfairAPI.BFGlobal;
    
    
    namespace BetfairControls
    {
        class MenuTreeNode : System.Windows.Forms.TreeNode
        {
            public  string    m_NodeType;
            public  int       m_id;
    
            public BetfairAPI.BFGlobal.EventType m_EventType;
            public BetfairAPI.BFGlobal.BFEvent m_bfEvent;
            public BetfairAPI.BFGlobal.MarketSummary m_MktSum;
    
            public MenuTreeNode( string Name )
            {
                this.Text = Name;
                m_NodeType = "Root";
    
            }
            public MenuTreeNode( BetfairAPI.BFGlobal.EventType eventType )
            {
                m_NodeType = "EventType";
                m_EventType = eventType;
                this.Text = eventType.name;
                this.m_id = eventType.id;
    
            }
    
            public MenuTreeNode( BetfairAPI.BFGlobal.BFEvent bfEvent )
            {
                m_NodeType = "bfEvent";
                m_bfEvent = bfEvent;
                this.Text = bfEvent.eventName;
                this.m_id = bfEvent.eventId;
    
            }
    
            public MenuTreeNode( BetfairAPI.BFGlobal.MarketSummary mktSum )
            {
                m_NodeType = "MarketSummary";
                m_MktSum = mktSum;
                if( mktSum.startTime.ToLocalTime().ToString( "HH:mm" ) != "00:00" )
                {
                    this.Text = mktSum.startTime.ToLocalTime().ToString( "HH:mm   " ) + mktSum.marketName;
                }
                else
                {
                    this.Text = mktSum.marketName;
                }
                this.m_id = mktSum.marketId;
            }
        }
    }
    Last edited by Escapee; 30-05-2012, 05:31 PM.

    Leave a comment:


  • AlgoTrader
    replied
    Originally posted by davecon View Post
    TI am using VB myself this is a great and helpful addition to my "Education"
    This is exactly what any Newbie is looking for regardless of the language
    When login and logout takes 135 lines of code something is very wrong there.

    Leave a comment:


  • davecon
    replied
    Thanks for this Escapee I think its brilliant when you knowledgeable guys take the time and effort to help us beginners although I am using VB myself this is a great and helpful addition to my "Education"
    This is exactly what any Newbie is looking for regardless of the language
    You are a star - Cheers

    Leave a comment:


  • AlgoTrader
    replied
    There are plenty of C# examples on the Betfair site. The tutorial achieved a challenging task - successful login to Betfair. It is useful and do real things, it shows how complex can be very simple things.

    I consider KISS principle the most important in programming. Things should be simple to work good. If tutorial ends at login step, it is certainly too early.

    Leave a comment:


  • wotsisname
    replied
    This should satisfy the newbies who often ask for C# examples. Keep up the good work Escapee. And ignore any snide comments...not everybody wants to learn a new programming language every time they start a new project.

    Leave a comment:


  • AlgoTrader
    replied
    Now I understand why it takes 4 months just to login.

    Leave a comment:


  • Escapee
    replied
    PART 3 Continued

    We're now going to add the code to our custom control that makes it respond to the
    user and talk to betfair to get the information required.
    This will involve adding code to the MenuTree.cs and CBetfairAPI.cs files.

    Step 26
    Adding new functionality to the CBetfairAPI class, namely the getActiveEventTypes() and getEvents()
    functions that are required to populate our menu with information about what markets are available.

    In the CBetfairAPI.cs file add the getActiveEventTypes() code after the 'Logout()' function

    Code:
            public bool getActiveEventTypes( ref GetEventTypesResp response )
            {
                bool bRetCode;
                const string serviceName = "getActiveEventTypes";
    
                Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1}", DateTime.Now, serviceName ) );
    
    
                var request = new GetEventTypesReq();
    
                request.header = _globReqHdr;
    
                response = _bfGlobal.getActiveEventTypes( request );
    
                bRetCode = CheckResponse( serviceName,
                                            Convert.ToString( response.header.errorCode ),
                                            Convert.ToString( response.errorCode ),
                                            response.header.sessionToken );
    
                if( bRetCode == false )
                {
                    return false;
                }
    
                //
                // If you want to see what is returned from this call then 
                // uncomment the foreach loop below
                //
                //foreach (EventType et in response.eventTypeItems)
                //{
                //    Debug.WriteLine(string.Format("EventItem: ({0}), ({1})", et.name, et.id));
                //}
    
    
                return true;
    
            }
    Step 27
    Add the getEvents code
    Code:
            public bool GetEvents( ref GetEventsResp response, int evtID )
            {
                bool bRetCode;
                const string serviceName = "getEvents";
    
                Debug.WriteLine( string.Format( "{0} - CBetfairAPI - {1}", DateTime.Now, serviceName ) );
    
    
                var request = new GetEventsReq();
    
                request.header = _globReqHdr;
                request.eventParentId = evtID;
    
                response = _bfGlobal.getEvents( request );
    
                bRetCode = CheckResponse( serviceName,
                                            Convert.ToString( response.header.errorCode ),
                                            Convert.ToString( response.errorCode ),
                                            response.header.sessionToken );
    
                if( bRetCode == false )
                {
                    return false;
                }
    
                return true;
            }

    Take a moment to review all the code in CBetfairAPI.cs, notice how similar
    all the 4 functions are ? LogOn(), LogOut(), getActiveEventTypes() and GetEvents()
    They all do completely different things and yet they all do it in pretty much the same
    way. But the last two: getActiveEventTypes() and GetEvents() require input data and
    or produce output data which we will want to process outside of the CBetfairAPI
    class. So this input and output data are passed about as parameters, but everything else
    is almost identical in all the functions.

    Writing Functions in a similar manner makes things a whole lot easier to read, understand and mantain.



    Step 28
    Back to the MenuTree Control

    Each "Event" and "Market" on betfair has its own ID and a Name which we'll need to store
    on the MenuTree for later use. So we're going to create a custom class just for this purpose.
    And because we are going to store this information on each node of the MenuTree, we will
    make it easy on ourselves and get our custom class to inherit from the standard "TreeNode"
    class.

    Right Click 'BetfairControls' and select the "Add->Class" menu option.
    Change the name to "MenuTreeNode" and click "Add"

    Step 29
    In the MenuTreeNode.cs file add the following code below the existing 'Using' Statements.

    Code:
    using System.Diagnostics;
    using BetfairAPI;
    using BetfairAPI.BFGlobal;

    Step 30

    Change the class definition so it inherits from "TreeNode"

    Code:
    public     class MenuTreeNode : System.Windows.Forms.TreeNode
        {
        }
    Step 31
    Within the empty braces '{' and '}' put the variables to Store our data ( and Constructors in Step 32 )
    Code:
            public  string    m_NodeType;
            public  int       m_id;
    
            public BetfairAPI.BFGlobal.EventType m_EventType;
            public BetfairAPI.BFGlobal.BFEvent m_bfEvent;
            public BetfairAPI.BFGlobal.MarketSummary m_MktSum;
    Step 32
    Because our menu is required to store 4 different sorts of things:
    root (top of the Menu Tree) , EventType (soccer etc), Event ( Man Utd v Aresenal etc ) and Market ( O/U 1.5 goals etc )
    We need a record of what type each node is ( stored in m_NodeType ) We then simply create
    4 different contructors for each of the 4 different NodeTypes.
    And handle 4 different node types with out needing a load of 'if then else' logic for each different type

    Add the code for the Contructors
    Code:
            public MenuTreeNode( string Name )
            {
                this.Text = Name;
                m_NodeType = "Root";
    
            }
            public MenuTreeNode( BetfairAPI.BFGlobal.EventType eventType )
            {
                m_NodeType = "EventType";
                m_EventType = eventType;
                this.Text = eventType.name;
                this.m_id = eventType.id;
    
            }
    
            public MenuTreeNode( BetfairAPI.BFGlobal.BFEvent bfEvent )
            {
                m_NodeType = "bfEvent";
                m_bfEvent = bfEvent;
                this.Text = bfEvent.eventName;
                this.m_id = bfEvent.eventId;
    
            }
    
            public MenuTreeNode( BetfairAPI.BFGlobal.MarketSummary mktSum )
            {
                m_NodeType = "MarketSummary";
                m_MktSum = mktSum;
                if( mktSum.startTime.ToLocalTime().ToString( "HH:mm" ) != "00:00" )
                {
                    this.Text = mktSum.startTime.ToLocalTime().ToString( "HH:mm   " ) + mktSum.marketName;
                }
                else
                {
                    this.Text = mktSum.marketName;
                }
                this.m_id = mktSum.marketId;
            }
    That completes the MenuTreeNode Class, give it a quick compile to check it does so
    with out error.
    Full Code for Part 3 is available at the end of Part 3.


    Step 34
    Now onto the MenuTree.cs file

    Add the Following code to just below the existing 'Using' Statements

    using System.Diagnostics;

    Code:
    using BetfairAPI;
    using BetfairAPI.BFGlobal;
    using BetfairAPI.BFExchange;
    Step 35
    Add a 'CBetfairAPI' variable and change the constructor to look like this:

    Code:
            public MenuTree()
            {
                InitializeComponent();
    
                m_Betfair = null;
            }
            public CBetfairAPI m_Betfair;
    In our "TestForm1" we instantiated ( i.e. new'ed ) an instance of the CBetfairAPI Class,
    which we then logged on to betfair with. For many various reasons, some of which are because the
    user will only be doing one action at a time and resources are ultimately finite,
    I prefer to stick to one instance of CBetfairAPI shared by and dedicated too all the
    user's gui actions and controls, And any background actions and threads which the user
    has no interaction with ( Such as automated market refreshing ) gets its own dedicated
    instance of the CBetfairAPI Class.
    So 'm_Betfair' will be pointed to the main GUI's instance of CBetfairAPI when the
    GUI initialises itself.

    Step 36
    Create the Initialise() function.
    This will be called from our TestForm1.ButLogOn_Click() event after a successful logon
    by the user.
    It loads up the top level of the Menu with all the different Event Types such as 'Horse Racing', 'Soccer' etc.

    Code:
            public bool Initialise()
            {
                this.Nodes.Clear();
    
                if( m_Betfair == null )
                {
                    return false;
                }
    
                GetEventTypesResp Response = new GetEventTypesResp();
    
                if( m_Betfair.getActiveEventTypes( ref Response ) != true )
                {
                    Debug.WriteLine( "Error: MenuTree->Initialise()->m_Betfair.getActiveEventTypes() FAILED ( returned false )" );
                    return ( false );
                }
    
                if( Response.eventTypeItems != null )
                {
                    foreach( EventType et in Response.eventTypeItems )
                    {
                        Debug.WriteLine( string.Format( "Init-----EventItem: ({0}), ({1})", et.name, et.id ) );
    
                        MenuTreeNode tNode = new MenuTreeNode( et );
    
                        this.Nodes.Add( tNode );
                    }
    
                }
                else
                {
                    Debug.WriteLine( "MenuTree->Initialise()->m_BetfairgetActiveEventTypes() returned 0 Events ?!" );
    
                }
                return true;
            }

    Step 37
    Now we're going to override the 'OnAfterSelect' event that is normally fired off by the standard
    "TreeView" Class with our own customised version of it.
    This will handle the processing required to enable drilling down of the menu from a top level
    'event type' such as 'Soccer' all the way to a specific market such as 'Over/Under 1.5 Goals'

    overrides are what make custom controls based on standard controls so powerful and easy to create.

    Code:
            override protected void OnAfterSelect( TreeViewEventArgs e )
            {
    
                MenuTreeNode tNode = (MenuTreeNode)e.Node;
    
                if( tNode.Nodes.Count == 0 )
                {
    
                    switch( tNode.m_NodeType )
                    {
                        case "bfEvent":
                        case "EventType":
    
                            GetEventsResp eventResp = new GetEventsResp();
    
                            if( m_Betfair.GetEvents( ref eventResp, tNode.m_id ) == false )
                            {
                                Debug.WriteLine( "OnAfterSelect()->GetEvents() Returned false ?!" );
                                return;
                            }
                            if( eventResp.eventItems != null )
                            {
    
                                foreach( BFEvent evt in eventResp.eventItems )
                                {
                                    Debug.WriteLine(string.Format("BFEvent: ({0}), ({1})", evt.eventName, evt.eventId));
    
                                    MenuTreeNode evtNode = new MenuTreeNode( evt );
                                    tNode.Nodes.Add( evtNode );
                                }
                            }
                            if( eventResp.marketItems != null )
                            {
                                foreach( MarketSummary mkt in eventResp.marketItems )
                                {
                                    Debug.WriteLine( string.Format( "MarketSummary: ({0}), ({1}), ", mkt.marketName, mkt.marketId ) );
    
                                    MenuTreeNode mktNode = new MenuTreeNode( mkt );
                                    tNode.Nodes.Add( mktNode );
                                }
                            }
                            tNode.Expand();
                            break;
    
    
                        case "MarketSummary":
    
                            // Market Summary Records are the end of the tree's branches
                            // When a user Clicks On a Market Summary Node, he really wants
                            // to load the market. Something we will do in a later part of
                            // This tutorial
    
                            Debug.WriteLine( string.Format( "User Clicked the Market: ({0}), ID  = ({1}), ", tNode.Text, tNode.m_id ) );
    
    
                            break;
    
                        default:
                            Debug.WriteLine( "Node = " + tNode.Text + " UNKNOWN Type = " + tNode.m_NodeType );
                            break;
                    }
    
                }
    
    
    
                base.OnAfterSelect( e );
            }
    Compile it all to check it does so with out errors

    We're almost there, The Customised Control is practically finished all we have to now
    is put it on our TestForm1 and hook it up with a few lines of Code...

    Step 38
    From the Form Designer, Create a copy of 'MenuTree' on the form.

    in the properties window, change the name to c_MenuTree, And select a BackColor
    I chose 'LightSteelBlue'

    And your form should be looking like this now




    Step 39
    Now we're going to Hook up the control with a few lines of Code in the Form1.cs file

    CHange the Form1() constructor to look like this
    Code:
            public Form1()
            {
                InitializeComponent();
    
                MyBetfair = new CBetfairAPI();
    
               [B][COLOR="Red"] c_MenuTree.m_Betfair = MyBetfair;[/COLOR][/B]
    
                bLoggedOn = false;
            }
    Step 40
    add The Menu Initialisation code to the ButLogOn_Click() event just after
    the line 'bLoggedOn = true'
    so that it looks like this:
    Code:
                    if( MyBetfair.Login( uuu, ppp ) == true )
                    {
                        bLoggedOn = true;
    
                        [B][COLOR="Red"]c_MenuTree.Initialise();[/COLOR][/B]
    
                        ButLogOn.Text = "Log Out";
                        this.Text = "Logged On To Betfair";
    
                    }

    THAT'S IT !

    Compile and run and you should have something like this to play with.



    END OF PART 3

    The Maximum size of a post in this forum is 20k Characters,
    So Have had to move the Complete code for this tutorial to a seperate post ( post no. 12 I Think )
    Last edited by Escapee; 30-05-2012, 05:08 PM.

    Leave a comment:


  • Escapee
    replied
    PART 3
    Adding controls to the GUI

    In part 3 I will take you through the steps required to create and add
    custom controls to the Form, specifically the 'MenuTree' which the user
    needs to navigate to a market.

    By The End of Part 3 you should have a working Betfair GUI looking like this



    A little preamble on organising your code in general....
    When you write your own custom controls, you might very well want
    to reuse them in other programs that you might write. This can be
    achieved easily by cutting and pasting code from one project to
    another but that approach has a major drawback in that if you ever
    enhance or change your custom control, the changes don't appear in
    each project using the control until you've cut'n pasted to all the
    other projects using the custom control.
    So what we do is put all the custom controls that we might reuse later
    in thier very own 'project' class library. So that when any changes are
    made to the control, all the various programs that use just have to be
    recompiled and hey presto, they are using the latest version.

    As the control we are about to create is the main Betfair Menu, and as
    most Betfair GUI programs you'll ever write will need a Betfair Menu
    control, this is a prime candidate to be the first reuseable control.
    and so we're going to create a "BetfairControls" Library for it.


    Your Starting postion for Part 3 should be from where Part 2 Ended.
    I.E. Open the "TestForm1" solution in Visual Studio, this should load
    the "BetfairAPI" project.



    Step 21

    Create a New 'Class Library' Project by Right CLicking the "Solution 'TestForm1' (2 Projects)"
    in Solution Explorer. Follow the Menu down to FILE->ADD->NEW PROJECT
    In the Add New Project Form which appears, select "Class Library", Change the name to "BetfairControls"
    and change the Location to "My Betfair" ( or what ever you named the folder you created BetfairAPI & TestForm1 in )



    Step 22
    Now that we have 3 seperate projects: BetfairAPI, BetfairControls & TestForm1 we need to
    set the references so that they know about each other.

    Select the 'BetfairControls' project in Solution Explorer and right click 'References'
    Select the "Add Reference" and then select the 'Projects' Tab from the 'Add Reference' form
    Now Select your "BetfairAPI" project and click OK

    That tells the "BetfairControls" Library about the "BetfairAPI" Library.
    We now need to repeat the process and tell "TestForm1" about "BetfairControls"
    So Right Click on "TestForm1"'s References, Add->Reference->Projects, and select "BetfairControls" ->OK

    If you expand all the references nodes in solution Explorer it should look like this:




    Step 23
    Creating the Betfair Menu Control

    Right Click the 'BetfairControls' project in Solution Explorer, ADD->User Control
    Change the name to "MenuTree" and click the "Add" button.


    In the main (designer) window we now have the blank canvas that is our custom control
    We're not actually going to use this canvas, instead were just going have our control
    inherit all the properties and functions of the standard issue "TreeView" class and
    then we can simply add extra functionality as required.

    Step 24

    Right Click "MenuTree.cs" and select the View Code option
    As a default, the MenuTree Class inherits UserControl, we need to change that to
    "TreeView" Like so:

    Code:
        public partial class MenuTree : TreeView
        {
            public MenuTree()
            {
                InitializeComponent();
            }
        }
    Step 25
    Save and compile... It DOESN'T COMPILE !!

    If you look in the output window you will see the Error:
    "error CS1061: 'BetfairControls.MenuTree' does not contain a definition for 'AutoScaleMode'..."

    Click on that error line and it will take you directly to the offending code line in the auto generated
    'MenuTree.Designer.cs' file.

    As our custom control no longer inherits from 'UserControl' we have no 'AutoScaleMode' property
    so we can just comment this line out like so

    Code:
        //this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    Save and Compile again..... This time it should compile properly.


    So now we've created our very own custom control, which is found in the
    Toolbox just like any standard control like a button, checkbox etc.
    And can be placed on a form like any other control




    PART 3 CONTINUES IN NEXT POST
    Last edited by Escapee; 18-07-2012, 05:13 PM.

    Leave a comment:

Working...
X