Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Monday, 13 October 2014
( c# | Delegate | Events )
  • Allows a class to send notifications to other classes or objects
    • Publisher raises the event
    • One or more subscribers process the event

eg Button –> click –> subscriber1, subscriber2

Events are based on delegates

Delegates

  • I need a variable that references a method
  • A delegate is a type that references methods (just like a class or struct)
    • public delegate void Writer(string message);

Delegates can be very useful.

// The type public delegate void NameChangedDelegate(string oldValue, string newValue); static void Main() { // NameChanged variable references a method OnNameChanged NameChangedDelegate NameChanged = new NameChangedDelegate(OnNameChanged); NameChanged("old", "new"); } // This method will execute when a private static void OnNameChanged(string oldvalue, string newvalue) { Console.WriteLine("Name changed from {0} to {1}", oldvalue, newvalue); }

and..

public delegate float RateDelegate(float a); private static float OnRate(float a) { throw new NotImplementedException(); } static void Main() { //RateDelegate rate = new RateDelegate(OnRate); // rate is a delegate variable RateDelegate rate; rate = (float a) => a*2; float x = 2f; float y = rate(x); float yy = rate(x);

Interesting code showing a delegate type being assigned to a method, and anonymous method.

 

eg want to know what

multiple subscribers to listen.. this is what events are for.

// Backing field (private) private string _name; public string Name { get { return _name; } set { if (_name != value) { var oldValue = _name; _name = value; // Announce to world that something has changed if (NameChanged != null) { // It has no idea what will be called, only that the signature will be string oldValue, string newValue NameChanged(oldValue, value); } } } } // Field of type NameChangedDelegate public NameChangedDelegate NameChanged;

Type:
public delegate void NameChangedDelegate(string oldValue, string newValue);

Listeners:
{ //... // Hooking up the delegate to point to another method // Setting the public Field (of type NameChangedDelegate) to a new delegate and passing the method // however anyone else can overwrite this //book.NameChanged = new NameChangedDelegate(OnNameChanged); // multicast delegate book.NameChanged += OnNameChanged; book.NameChanged += OnNameChanged; book.NameChanged += OnNameChanged2; // ahh would wipe out the previous ones book.NameChanged = new NameChangedDelegate(OnNameChanged2); book.Name = "Allen's Book"; WriteNames(book.Name); Console.WriteLine(stats.AverageGrade); Console.WriteLine(stats.LowestGrade); Console.WriteLine(stats.HighestGrade); } private static void OnNameChanged2(string oldvalue, string newvalue) { Console.WriteLine("***"); } // This method will execute when a private static void OnNameChanged(string oldvalue, string newvalue) { Console.WriteLine("Name changed from {0} to {1}", oldvalue, newvalue); }

Notice the error above – wipes out the previous method delegate calls.

Next to use an event – prevent wiping out subscribers.

Events

Events are just delegates. 0:11 of 8:35

class Program { // The type public delegate void NameChangedDelegate(string oldValue, string newValue); static void Main() { // NameChanged variable references a method OnNameChanged NameChangedDelegate nameChanged = new NameChangedDelegate(OnNameChanged); nameChanged("old", "new"); } // This method will execute when a private static void OnNameChanged(string oldvalue, string newvalue) { Console.WriteLine("Name changed from {0} to {1}", oldvalue, newvalue); } }

Here is the working code with a delegate

class Program2 { // The type public delegate void NameChangedDelegate(string oldValue, string newValue); public static event NameChangedDelegate NameChanged; static void Main() { // NameChanged variable references a method OnNameChanged NameChanged += new NameChangedDelegate(OnNameChanged); NameChanged("old", "new"); } private static void OnNameChanged(string oldvalue, string newvalue) { Console.WriteLine("Name changed from {0} to {1}", oldvalue, newvalue); } }

Same with an Event.

class Program3 { public delegate void NameChangedDelegate(object sender, NameChangedEventArgs e); public static event NameChangedDelegate NameChanged; static void Main() { // NameChanged variable references a method OnNameChanged NameChanged += new NameChangedDelegate(OnNameChanged); //Convention in events: never pass arbitrary params NameChanged(null, new NameChangedEventArgs {OldValue = "old", NewValue = "new"}); } private static void OnNameChanged(object sender, NameChangedEventArgs e) { Console.WriteLine("Name changed from {0} to {1}", e.OldValue, e.NewValue); } } public class NameChangedEventArgs : EventArgs { public string OldValue { get; set; } public string NewValue { get; set; } }

Event using EventArgs (convention).  Using a static method so had to pass null instead of this.

 

Syntactically the same

public event NameChangedDelegate NameChanged;
No longer legal to assign to an event (which wiped out previous method delegate calls above)

Thats what special about events – needs a += or –= assignment

public class NameChangedEventArgs : EventArgs { public string OldValue { get; set; } public string NewValue { get; set; } }

Derives from EventArgs
public delegate void NameChangedDelegate(object sender, NameChangedEventArgs args);
 
private static void OnNameChanged(object sender, NameChangedEventArgs args){ Console.WriteLine("Name changed from {0} to {1}", args.OldValue, args.NewValue); }
Convention in events: never pass arbitrary params.. sender (eg gradebook) itself, then object that encapsulates other stuff

Members

Members are used to craft an abstraction

  • Fields and properties for state
  • Methods for behaviour
  • Events for notification
| | # 
# Wednesday, 28 December 2011

Delegates – “they encapsulate a bit of behaviour”.. Initally from Jon Skeets Tekpub videos:

    public delegate void Int32Action(int value);

    public class Delegates
    {
        public void RandomRob(int value)
        {
            Console.WriteLine("Delegate implementation: {0}", value);  
        }

        //static means related to the type rather than any specific instance of the type
        public static void StaticRob(int value)
        {
            Console.WriteLine("Static method: {0}", value);  
        }
    }

and calling:

        [Test]
        public void SimpleDelegateFromMethod()
        {
            Delegates target = new Delegates();
            //C#1 syntax
            Int32Action action = new Int32Action(target.RandomRob);

            //same.. calling the delegate which has been setup to be target.RandomRob
            action.Invoke(5);
            action(6);
        }

        [Test]
        public void DelegateFromStaticMethod()
        {
            Int32Action action = new Int32Action(Delegates.StaticRob);
            action.Invoke(7);
        }

 

Events

Observer pattern.

Here we are using pub/sub without events:

    [TestFixture]
    public class FakeEventRaiserTest
    {
        private void ReportToConsole(string text)
        {
            Console.WriteLine("Called: {0}", text);
        }

        [Test]
        public void RaiseEvents()
        {
            //C#1
            //FakeEventHandler handler = new FakeEventHandler(ReportToConsole);
            //C#2 - implicit method group conversions
            FakeEventHandler handler = ReportToConsole;

            FakeEventRaiser raiser = new FakeEventRaiser();
            raiser.DoSomething("Not subscribed");

            raiser.AddHandler(handler);
            raiser.DoSomething("Subscribed");
            
            raiser.AddHandler(handler);
            raiser.DoSomething("Subscribed twice");

            raiser.RemoveHandler(handler);
            raiser.RemoveHandler(handler);
            raiser.DoSomething("Unsubscribed");
        }
    }

asdf

public class FakeEventRaiser
    {
        private FakeEventHandler currentHandler = null;

        public void AddHandler(FakeEventHandler handler)
        {
            currentHandler = currentHandler + handler;
        }

        public void RemoveHandler(FakeEventHandler handler)
        {
            currentHandler = currentHandler - handler;
        }

        public void DoSomething(string text)
        {
            FakeEventHandler tmp = currentHandler;
            if (tmp!=null)
                tmp.Invoke(text);
        }
    }

Longhand EventRaiser:

[TestFixture]
    public class LonghandEventRaiserTest
    {
        private void ReportToConsole(object sender, EventArgs e)
        {
            Console.WriteLine("ReportToConsole was called");
        }

        [Test]
        public void RaiseEvents()
        {
            //C#1
            //FakeEventHandler handler = new FakeEventHandler(ReportToConsole);
            //C#2 - implicit method group conversions
            ClickHandler handler = ReportToConsole;

            var raiser = new LonghandEventRaiser();
            raiser.OnClick("Not subscribed");

            raiser.Click += handler;
            raiser.OnClick("Subscribed");

            raiser.Click += handler;
            raiser.OnClick("Subscribed twice");

            raiser.Click -= handler;
            raiser.Click -= handler;
            raiser.OnClick("Unsubscribed");
        }
    }

asdf

namespace MasteringCSharp.Tests
{
    public delegate void ClickHandler(object sender, EventArgs e);

    public class LonghandEventRaiser
    {
        private ClickHandler currentHandler = null;

        private void AddHandler(ClickHandler handler)
        {
            currentHandler = currentHandler + handler;
        }

        private void RemoveHandler(ClickHandler handler)
        {
            currentHandler = currentHandler - handler;
        }

        public void OnClick(string text)
        {
            ClickHandler tmp = currentHandler;
            if (tmp!=null)
                tmp.Invoke(this, EventArgs.Empty);
        }

        public event ClickHandler Click
        {
            add { AddHandler(value);}
            remove {RemoveHandler(value);}
        }
    }
}

but can simplify..fairly simple implementation of the observer pattern:

    public delegate void ClickHandler(object sender, EventArgs e);

    public class LonghandEventRaiser
    {
        private ClickHandler currentHandler = null;

        public void OnClick(string text)
        {
            ClickHandler tmp = currentHandler;
            if (tmp!=null)
                tmp.Invoke(this, EventArgs.Empty);
        }

        public event ClickHandler Click
        {
            add { currentHandler += value; }
            remove {currentHandler -= value;}
        }
    }

but we can do better!

public void OnClick(string text)
        {
            //Click refers to the field which is auto genned
            ClickHandler tmp = Click;
            if (tmp!=null)
                tmp.Invoke(this, EventArgs.Empty);
        }

        //declared with a field like event
        public event ClickHandler Click;

 

 

Other Ways of thinking of Delegates and Events

“An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object”

http://www.akadia.com/services/dotnet_delegates_and_events.html

Calling a function directly:

    class Program
    {
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();
            string result = mc.Process();
            Console.WriteLine(result);
        }
    }

    public class MyClass
    {
        public string Process()
        {
            return "In Process";
        }
    }

Basic Delegate

Sometimes we don’t want to call a function directly – we’d like to pass it to somebody else so they can call it.

    class Program
    {
        private delegate void LogDelegate(string s);

        static void Main(string[] args)
        {
            LogDelegate consoleLog = new LogDelegate(ConsoleLoggerFunction);
            consoleLog.Invoke("hello world");
            consoleLog("Another way");
        }

        static void ConsoleLoggerFunction(string s)
        {
            Console.WriteLine("Message is: {0}", s);
        }
    }

Calling Static Functions

    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();
            Person.LogDelegate logger = new Person.LogDelegate(Logger);
            //implicit method group conversion
            //Person.LogDelegate logger = Logger;
            p.Process(logger);
        }

        private static void Logger(string message)
        {
            Console.WriteLine(message);
        }
    }

    public class Person
    {
        public delegate void LogDelegate(string message);

        public void Process(LogDelegate logDelegate)
        {
            if (logDelegate != null)
                logDelegate.Invoke("Doing stuff");
        }
    }

and then use a FakeLogger in tests:

        [Test]
        public void Process_WhenCalled_ShouldWriteToLogPassedIntoDelegate()
        {
            Person p = new Person();
            Person.LogDelegate logDelegate = new Person.LogDelegate(FakeLogger);

            p.Process(logDelegate);

        }

        private void FakeLogger(string message)
        {
            Console.WriteLine("FakeLogger: {0}", message);
        }

or could have simply used an interface:

******below is just for reference****** actually in the interest of keeping things simple, am going to go for more of an interface style in my TDD/Logging strategy as eventing can get complex quickly.

Calling Member Functions

hmm – could be better

internal class MyClass
    {
        //takes a single string parameter and no return type
        public delegate void LogHandler(string message);

        public void Process(LogHandler lh)
        {
            if (lh != null)
                lh("Process() begin");
            if (lh != null)
                lh("Process() end");
        }
    }

    // The FileLogger class merely encapsulates the file I/O
    public class FileLogger
    {
        FileStream fileStream;
        StreamWriter streamWriter;

        // Constructor
        public FileLogger(string filename)
        {
            fileStream = new FileStream(filename, FileMode.Create);
            streamWriter = new StreamWriter(fileStream);
        }

        // Member Function which is used in the Delegate
        public void Logger(string s)
        {
            streamWriter.WriteLine(s);
        }

        public void Close()
        {
            streamWriter.Close();
            fileStream.Close();
        }
    }

    public class TestApplication
    {
        static void Main(string[] args)
        {
            FileLogger fl = new FileLogger("process.log");
            MyClass mc = new MyClass();

            MyClass.LogHandler myLogger = new MyClass.LogHandler(fl.Logger);
            mc.Process(myLogger);
            fl.Close();
        }
    }

Events

  • Publishers
  • Subscribers

want a simple example of a logger using events - http://stackoverflow.com/questions/8663736/delegate-and-events-architecture-with-a-logger

public class Person
    {
        //takes a single string parameter and no return type
        public delegate void LogHandler(string message);

        // Define an Event based on the above Delegate
        public event LogHandler Log;

        //call the event using OnXXX where XXX is the name of the event
        public void Process()
        {
            OnLog("Process() begin");
            OnLog("Process() end");
        }

        protected void OnLog(string message)
        {
            if (Log != null)
                Log(message);
        }
    }

    public class FileLogger
    {
        FileStream fileStream;
        StreamWriter streamWriter;

        public FileLogger(string filename)
        {
            fileStream = new FileStream(filename, FileMode.Create);
            streamWriter = new StreamWriter(fileStream);
        }

        // Member Function which is used in the Delegate
        public void Logger(string s)
        {
            streamWriter.WriteLine(s);
        }

        public void Close()
        {
            streamWriter.Close();
            fileStream.Close();
        }
    }

    public class TestApplication
    {
        static void ConsoleLogger(string s)
        {
            Console.WriteLine(s);
        }

        static void Main(string[] args)
        {
            FileLogger fl = new FileLogger("process.log");
            Person person = new Person();

            // Subscribe the Functions ConsoleLogger and fl.ConsoleLogger
            person.Log += new Person.LogHandler(ConsoleLogger);
            person.Log += new Person.LogHandler(fl.Logger);

            person.Process();

            fl.Close();
        }
    }

and then:

    public delegate void FakeEventHandler(string reason);

    public class FakeEventRaiser
    {
        private FakeEventHandler currentHandler = null;

        public void AddHandler(FakeEventHandler handler)
        {
            currentHandler = currentHandler + handler;
        }

        public void RemoveHandler(FakeEventHandler handler)
        {
            currentHandler = currentHandler - handler;
        }

        public void DoSomething(string text)
        {
            FakeEventHandler tmp = currentHandler;
            if (tmp!=null)
                tmp.Invoke(text);
        }
    }
| | # 
# Wednesday, 04 November 2009
I know I've skipped a few chapters.. but hey.. who is perfect?  Sometimes, it is good to get to some concrete results to give some pespective.

After months of playing with code (why do things always take longer than you think..?), and having a blast, I've now forgotton everything I know about asp.net.  So time to do some spikes.

Here is a super simple reminder of asp.net syntax and simple events:

Default.aspx (\code\tddBook\SimpleAspSpike)

<%@ Page Language="C#" AutoEventWireup="true"  CodeBehind="Default.aspx.cs" Inherits="WebSite2testWebProj._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form2" runat="server">
    <div>
    hello world from html<br />
    <%= "Hello from asp.net" %> <br />
    
    This is a label: <asp:Label ID="label1" runat="server" /> <br />
    The time is: <%= System.DateTime.Now.ToLongTimeString()%> <br />
    This is a textbox: <asp:TextBox runat="server" ID="textbox1" /><br />
    A button: <asp:Button runat="server" ID="button1" Text="press me" onclick="button1_Click" /><br />
   Label2 is here: <asp:Label ID="label2" runat="server" /><br />
   asp.net uses viewstate.. so the button is just a submit button, which then goes back to the server, refreshes the page with the new data in the label2 label. <br />    
    </div>
    Autopostback is set in the following DropDownList (server control)... makes contact with the server each time an item is selected.. which we can use to wire up an event..onselectedindexchanged<br />
    <asp:DropDownList runat="server" ID="GreetList" AutoPostBack="true" 
        onselectedindexchanged="GreetList_SelectedIndexChanged">
        <asp:ListItem Value="no one">No one</asp:ListItem>
        <asp:ListItem Value="world">World</asp:ListItem>
        <asp:ListItem Value="universe">Universe</asp:ListItem>
    </asp:DropDownList><br />
    Label3: <asp:Label ID="label3" runat="server" /> <br />
    </form>
</body>
</html>

And the Default.aspx.cs

using System;
using System.Web.UI;

namespace WebSite2testWebProj
{
    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write("Hello from Page_Load in codebehind");
            label1.Text = "Hello from the codebehind into a label";
            textbox1.Text = "Textbox from codebehind";
        }

        protected void button1_Click(object sender, EventArgs e)
        {
            label2.Text = "button pressed";
        }

        protected void GreetList_SelectedIndexChanged(object sender, EventArgs e)
        {
            label3.Text = "Hello, " + GreetList.SelectedValue;
        }
    }
}

Ok, looking good so far.

Difference between CodeBehind and CodeFile

WebSite or Web Application Project?
http://www.dotnetspider.com/resources/1520-Difference-between-web-site-web-application.aspx

WebSite is really simple, with no project file.  Web Application Project has a project file.

Found that remembering how to access databases isn't too easy:

looking at old project:
http://treasuresprint.blogspot.com

Realised I didn't put up the sourcecode at the time, and have managed to find it on my laptop:


Connecting to and displaying data from a DB very easily:

Deafult.aspx (\code\tddBook\DBConnectySpike)
<form id="form1" runat="server">
    <div>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TreasureConnectionString %>"
            SelectCommand="SELECT [StuffId], [Description] FROM [Stuff]"></asp:SqlDataSource>
        <br />
        <br />
        this is a gridview&nbsp;<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
            DataKeyNames="StuffId" DataSourceID="SqlDataSource1">
            <Columns>
                <asp:BoundField DataField="StuffId" HeaderText="StuffId" InsertVisible="False" ReadOnly="True"
                    SortExpression="StuffId" />
                <asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
            </Columns>
        </asp:GridView>
        <br />
        this is a datalist<br />
        <br />
        <asp:DataList ID="DataList1" runat="server" DataSourceID="SqlDataSource1" >
            <ItemTemplate>
                <asp:Literal ID="Literal2" runat="server" Text="Description:"></asp:Literal>
                <asp:Literal ID="Literal1" runat="server" Text='<%# Eval("Description") %>'></asp:Literal>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:Literal ID="Literal2" runat="server" Text="Description:"></asp:Literal>
                <asp:TextBox ID="TextBox1" runat="server" Text='<%# Eval("Description") %>' Width="208px"></asp:TextBox>
            </EditItemTemplate>
        </asp:DataList><br />
        <br />
        this is a details view</div>
        <asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" CellPadding="4"
            DataKeyNames="StuffId" DataSourceID="SqlDataSource1" ForeColor="#333333" GridLines="None"
            Height="50px" Width="341px">
            <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <CommandRowStyle BackColor="#D1DDF1" Font-Bold="True" />
            <EditRowStyle BackColor="#2461BF" />
            <RowStyle BackColor="#EFF3FB" />
            <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
            <Fields>
                <asp:BoundField DataField="StuffId" HeaderText="StuffId" InsertVisible="False" ReadOnly="True"
                    SortExpression="StuffId" />
                <asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
            </Fields>
            <FieldHeaderStyle BackColor="#DEE8F5" Font-Bold="True" />
            <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <AlternatingRowStyle BackColor="White" />
        </asp:DetailsView>
        <br />
        <br />
    </form>
And in the web.config:
<connectionStrings>
    <add name="TreasureConnectionString" connectionString="Data Source=localhost;Initial Catalog=Treasure;Persist Security Info=True;User ID=dave;Password=letmein" providerName="System.Data.SqlClient"/>
    </connectionStrings>
So it should come out like this:


Thoughts
ASP.NET offers some controls to make life 'easier' such as databinding, edit, deleting, sorting on the gridview:  All pretty powerful for RAD, however for testable apps.. am not sure this is the way.  Or perhaps other Grid controls like Telerik are better.  Maybe best to Keep it Simple.

Ideally we want testable code, with a thin layer of UI code on top.
A gridview with update
        <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:TreasureConnectionString %>" 
        SelectCommand="SELECT [StuffId], [Description] FROM [Stuff]"
        UpdateCommand="UPDATE Stuff SET Description=@Description WHERE StuffID=@StuffID">
        </asp:SqlDataSource>
         <asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" DataKeyNames="StuffId" AutoGenerateEditButton="true" DataSourceID="SqlDataSource2">
           <Columns>
                <asp:BoundField DataField="StuffId" HeaderText="StuffId"/>
                <asp:BoundField DataField="Description" HeaderText="Description"/>
            </Columns>
         </asp:GridView>


And DropDownList / TextBox common usage:




This is all in the DB spike source code here:
DBConnectSpike.zip (15.17 KB)

Data Control Summary
http://quickstarts.asp.net/QuickStartv20/aspnet/doc/ctrlref/data/default.aspx

Gridview - the classic Grid..edit, delete, sort, page.  Takes advantage of DataSource controls
DataList - items in a repeating list
DetailsView - typically used.. if a gridview item is selected, the detailsView is displayed to edit.
FormView - same as above but with no built in template.
Repeater - has no built in layout or styles.  No column layout. No Edit/Del

Going through the SearchPage.aspx.. trying to get any of this application to compile.  Have got source from book.. however..  good practise to chop code and and try and work through.  Hmm - sometimes better to revert back to compiling code in source control.

This project is in need of refactoring... too complex currently.  Would like to 'defactor' for simplicity, then put some patterns back in.  Webservice would be first to go, and use POCOs.  XSD definition for DTOs would go as well, with simple objects as definitions.  DAL I'd like to take out Datasets and use a manual DAL.

Most important thing is to get it working.  Good thing about this project so far, is that it is testable at every level.
| | # 
# Wednesday, 25 February 2009


Thanks to the original author of the code (google m7tr1x)..

I had some great fun looking at the code, understanding how this effect works, and refactoring.

The original code is below.. I suggest scrolling down, and looking at the refactored code and pictures describing how the effect works.

Enjoy!

#define readkey

using System;

namespace m7tr1x
{
    class Program
    {
        static void Main(string[ ] args)
        {
            Console.Title = "tH3 M7tr1x 3ff3<t";
            Console.ForegroundColor = ConsoleColor.DarkGreen;
            Console.WindowLeft = Console.WindowTop = 0;
            Console.WindowHeight = Console.BufferHeight = Console.LargestWindowHeight;
            Console.WindowWidth = Console.BufferWidth = Console.LargestWindowWidth;
#if readkey
            Console.WriteLine("H1T 7NY K3Y T0 C0NT1NU3 =/");
            Console.ReadKey();
#endif
            Console.CursorVisible = false;
            int width, height;
            int[ ] y;
            int[ ] l;
            Initialize(out width, out height, out y, out l);
            int ms;
            while ( true )
            {
                DateTime t1 = DateTime.Now;
                MatrixStep(width, height, y, l);
                ms = 10 - (int)( (TimeSpan)( DateTime.Now - t1 ) ).TotalMilliseconds;
                if ( ms > 0 )
                    System.Threading.Thread.Sleep(ms);
                if ( Console.KeyAvailable )
                    if ( Console.ReadKey().Key == ConsoleKey.F5 )
                        Initialize(out width, out height, out y, out l);
            }
        }

        static bool thistime = false;

        private static void MatrixStep(int width, int height, int[ ] y, int[ ] l)
        {
            int x;
            thistime = !thistime;
            for ( x = 0 ; x < width ; ++x )
            {
                if ( x % 11 == 10 )
                {
                    if ( !thistime )
                        continue;
                    Console.ForegroundColor = ConsoleColor.White;
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.DarkGreen;
                    Console.SetCursorPosition(x, inBoxY(y[x] - 2 - ( l[x] / 40 * 2 ), height));
                    Console.Write(R);
                    Console.ForegroundColor = ConsoleColor.Green;
                }
                Console.SetCursorPosition(x, y[x]);
                Console.Write(R);
                y[x] = inBoxY(y[x] + 1, height);
                Console.SetCursorPosition(x, inBoxY(y[x] - l[x], height));
                Console.Write(' ');
            }
        }

        private static void Initialize(out int width, out int height, out int[ ] y, out int[ ] l)
        {
            int h1;
            int h2 = ( h1 = ( height = Console.WindowHeight ) / 2 ) / 2;
            width = Console.WindowWidth - 1;
            y = new int[width];
            l = new int[width];
            int x;
            Console.Clear();
            for ( x = 0 ; x < width ; ++x )
            {
                y[x] = r.Next(height);
                l[x] = r.Next(h2 * ( ( x % 11 != 10 ) ? 2 : 1 ), h1 * ( ( x % 11 != 10 ) ? 2 : 1 ));
            }
        }

        static Random r = new Random();
        static char R
        {
            get
            {
                int t = r.Next(10);
                if ( t <= 2 )
                    return (char)( '0' + r.Next(10) );
                else if ( t <= 4 )
                    return (char)( 'a' + r.Next(27) );
                else if ( t <= 6 )
                    return (char)( 'A' + r.Next(27) );
                else
                    return (char)( r.Next(32, 255) );
            }
        }

        public static int inBoxY(int n, int height)
        {
            n = n % height;
            if ( n < 0 )
                return n + height;
            else
                return n;
        }
    }
}
Here is the refactored code:
using System;

namespace matrix
{
    class Program
    {
        // fields
        static Random rand = new Random();
        
        // properties
        static char AsciiCharacter
        {
            get
            {
                int t = rand.Next(10);
                if (t <= 2)
                    // returns a number
                    return (char)('0' + rand.Next(10));
                else if (t <= 4)
                    // small letter
                    return (char)('a' + rand.Next(27));
                else if (t <= 6)
                    // capital letter
                    return (char)('A' + rand.Next(27));
                else
                    // any ascii character
                    return (char)(rand.Next(32, 255));
            }
        }

        // methods
        static void Main()
        {
            Console.ForegroundColor = ConsoleColor.DarkGreen;
            Console.WindowLeft = Console.WindowTop = 0;
            Console.WindowHeight = Console.BufferHeight = Console.LargestWindowHeight;
            Console.WindowWidth = Console.BufferWidth = Console.LargestWindowWidth;
            Console.WriteLine("Hit Any Key To Continue");
            Console.ReadKey();
            Console.CursorVisible = false;
            
            int width, height;
            // setup array of starting y values
            int[] y;

            // width was 209, height was 81
            // setup the screen and initial conditions of y
            Initialize(out width, out height, out y);

            // do the Matrix effect
            // every loop all y's get incremented by 1
            while ( true )
                UpdateAllColumns(width, height, y);
        }

        
        private static void UpdateAllColumns(int width, int height, int[] y)
        {
            int x;
            // draws 3 characters in each x column each time... 
            // a dark green, light green, and a space

            // y is the position on the screen
            // y[x] increments 1 each time so each loop does the same thing but down 1 y value
            for ( x = 0 ; x < width ; ++x )
            {
                // the bright green character
                Console.ForegroundColor = ConsoleColor.Green;
                Console.SetCursorPosition(x, y[x]);
                Console.Write(AsciiCharacter);

                // the dark green character -  2 positions above the bright green character
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                int temp = y[x] - 2;
                Console.SetCursorPosition(x, inScreenYPosition(temp, height));
                Console.Write(AsciiCharacter);

                // the 'space' - 20 positions above the bright green character
                int temp1 = y[x] - 20;
                Console.SetCursorPosition(x, inScreenYPosition(temp1, height));
                Console.Write(' ');

                // increment y
                y[x] = inScreenYPosition(y[x] + 1, height);
            }

            // F5 to reset, F11 to pause and unpause
            if (Console.KeyAvailable)
            {
                if (Console.ReadKey().Key == ConsoleKey.F5)
                    Initialize(out width, out height, out y);
                if (Console.ReadKey().Key == ConsoleKey.F11)
                    System.Threading.Thread.Sleep(1);
            }

        }

        // Deals with what happens when y position is off screen
        public static int inScreenYPosition(int yPosition, int height)
        {
            if (yPosition < 0)
                return yPosition + height;
            else if (yPosition < height)
                return yPosition;
            else
                return 0;
        }

        // only called once at the start
        private static void Initialize(out int width, out int height, out int[] y)
        {
            height = Console.WindowHeight;
            width = Console.WindowWidth - 1;

            // 209 for me.. starting y positions of bright green characters
            y = new int[width];
            
            Console.Clear();
            // loops 209 times for me
            for ( int x = 0 ; x < width ; ++x )
            {
                // gets random number between 0 and 81
                y[x] = rand.Next(height);
            }
        }
    }
}

how it works:

The screen draws each column.. my screen is 208 wide.. so it loops 208 times, each time drawing a bright green character, dark green character, and a space.



The second loop.. the y value has been incremented by 1.



The 3rd loop



Enjoy!
| | # 
# Friday, 07 November 2008
( Events )
Christchurch CodeCamp 2008 was a resounding success:


Setting up Friday evening Andy, MattT, MattS.. a giant puzzle!


Here is Mats entertaining presentation on SQL 2008 for Developers:  CodeCamp_MatVelloso.zip (941.34 KB)

Other great presentations were:

Ivan Towlson - Thinking in WPF
http://hestia.typepad.com/flatlander/2008/11/christchurch-code-camp-2008---thinking-in-wpf.html

Andy Scrase - A C#3.0 Whirlwind Tour
http://buildwith.net

John Rusk - LINQ to SQL Optimation
http://dotnet.agilekiwi.com/blog/2008/11/linq-to-sql-presentation.html

Ben Reid - Could Computing
http://cloudservices.blogspot.com

--------------------
After lunch

Lightning:
Gary Payne on jQuery
http://sharethelearning.blogspot.com/2008/11/jquery-introduction-talk-at.html

Matt Tester
http://pureblue.wordpress.com/2008/11/04/christchurch-code-camp-design-with-paper-prototypes/

Matt Smith - Sharepoint Development
http://blog.mattsmith.co.nz

Del Robinson - Tour of BI Projects and technology
http://www.omegatech.co.nz/powerpoints/Business_Intelligence_StatisticsNZ.ppt

Dave Roys - Navision Perspective
http://gaspodethewonderdog.blogspot.com/2008/11/codecamp-2008-nav-resources.html

Kirk Jackson - Overcoming your Web Insecurity
http://pageofwords.com/blog/2008/11/01/ChristchurchCodeCampOvercomingYourWebInsecurity.aspx
http://pageofwords.com/blog/2008/11/02/LearningsFromChristchurchCodeCamp.aspx



MattS.. The sign says Recovery








| | #