Smartssolutions

Wednesday, October 5, 2011

Using delegates in C#

Deleagtes could be used in several senarios

extend a classA in a classB

 //Source object

class ClassA
    {
        //Deleagte declaration
        public MyDelegate myDelegate;
    }
   

//Destination object
    class ClassB
    {
        ClassA classA;
        public ClassB()
        {
            // ClassA initailization
            classA = new ClassA();
            //Extend the classA
            classA.myDelegate += new MyDelegate(Method);
            //Call the method
            classA.myDelegate();
           
        }
        public void Method()
        {
            Console.WriteLine("Bonjour");
        }
    }

Events are based on  Delegetes

class CustomEventArgs : EventArgs
    {
        public string Message{get; set;}
        public CustomEventArgs(string Message)
        {
            this.Message = Message;
        }
    }

class Trigger
    {
       
        public delegate void EventHandler(Object sender, CustomEventArgs ce);
       
       
        public event EventHandler TriggerEvent;
       
        public void OnTriggerEvent(string Message)
        {
            TriggerEvent(this, new CustomEventArgs(Message));
        }
    }

To consume this event:

class Program
  {
    static void Main(string[] args)
        {
           
            Trigger trigger = new Trigger();
           
            trigger.TriggerEvent+=new Trigger.EventHandler(trigger_TriggerEvent);
           
            trigger.OnTriggerEvent("Hello");
           
            trigger.OnTriggerEvent("How are you!! ; )");
           Console.Read();
        }
    static void trigger_TriggerEvent(object sender, CustomEventArgs ce)
    {
     Console.WriteLine("Event is triggered and the message is {0}", ce.Message);
    }
}


Delegate are used whithin Threading context as Callback operators those call methods executed within  given threads' contexts

System.Threading.ThreadStart threadStart;
Thread myThread;
void Main
{

threadStart = new ThreadStart(Method);
myThread = new Thread(threadStart);
myThread.Start();
}

static void Method()
     {
         Console.WriteLine("Thread is lunched");
     }

And so many other cases

A senario of implementing a custom event

In this blog I will represent two senario of implementing a custom event one without arguments and other with arguments

Hi
Here is a full implementation of both senarios when using event args and when using a custom event args to pass some information when raising events
namespace ConsoleApplication1
{  
  class Program
  {
    static void Main(string[] args)
    {
      //Without arguements
      EventClass eventClass = new EventClass();
      eventClass.CustomEvent+=new EventHandler(eventClass_CustomEvent);

      //With arguements
      EventWithArguementsClass eventwithargclass = new EventWithArguementsClass();
      eventwithargclass.CustomEvent+=new EventWithArguementsClass.CustomEventHandler(eventwithargclass_CustomEvent);
      Console.Read();
    }

    static void eventClass_CustomEvent(object sender, EventArgs args)
    {
      Console.WriteLine("The event is raised");
    }

    static void eventwithargclass_CustomEvent(object sender, CustomEventArgs args)
    {
      args.Message = "The event with parameters is raised";
      Console.WriteLine(args.Message);
    }

  }//Class

  //Class sample with event args, used when you don't need to pass some information throught
  class EventClass
  {
    private event EventHandler customEvent;

    public event EventHandler CustomEvent
    {
      add { customEvent += value; OnCustomEvent(); }
      remove { customEvent -= value; }
    }

    protected void OnCustomEvent()
    {
      if (null!= customEvent)
      {
        customEvent(this, new EventArgs());
      }
    }

  }//Class
  //Class sample with event args, used when you need to pass some information throught like the message
  class EventWithArguementsClass
  {
    public delegate void CustomEventHandler(object sender, CustomEventArgs args);
    private event CustomEventHandler customEvent;
    private string message=string.Empty; 

    public event CustomEventHandler CustomEvent
    {
      add { customEvent += value; OnCustomEvent(message); }
      remove { customEvent -= value; }
    }

    protected void OnCustomEvent(string message)
    {
      if (null != customEvent)
      {
        customEvent(this, new CustomEventArgs(message));
      }
    }

  }
  class CustomEventArgs:EventArgs
  {
    public string Message { get; set; }

    public CustomEventArgs(string message)
    {
      Message = message;
    }
  }



How to sort an infinite collection

In one of my MSDN posts  they asked me how to sort an infinite collection and my response was to create a private custom collection object as follow:

public class MyArray<T> : ICollection<T>
 {
  private List<T> list;
  public delegate void CustomSortEventHandler(object sender, CustomSortEventArgs<T> customeventargs);
  public MyArray()
  {
   list = new List<T>();  
  }
  //You have to focus on that event that is triggered each time a new item is added
  private event CustomSortEventHandler sortEvent;
  public event CustomSortEventHandler SortEvent
  {
   add { sortEvent += SortEventHandler; OnSortEvent(); }
   remove { sortEvent -= SortEventHandler; }
  }
  public Comparison<T> Comparaison { get; set; }
  protected void OnSortEvent()
  {
   if (sortEvent!=null)
   {

    sortEvent(this, new CustomSortEventArgs<T>(Comparaison));
   }
  }
  //Here is the event handler that sorts data in the list
  protected void SortEventHandler(object sender, CustomSortEventArgs<T> args)
  {
   if (Comparaison==null)
   {
    list.Sort(); 
   }
   else
   {
    list.Sort(Comparaison);
   }
  }

  //Here is the indexed property
  public T this[int index]
  {
   get { return list[index]; }
   set { list.Add(value);/*You add an event handler at this point*/ this.SortEvent += SortEventHandler; }
  }
  
  public void Add(T item)
  {
   list.Add(item);
   //You add an event handler at this point
   this.SortEvent += SortEventHandler;
  }
  #region rest of the iCollection methods
  public void Clear()
  {
   list.Clear();
  }

  public bool Contains(T item)
  {
   return list.Contains(item);
  }

  public void CopyTo(T[] array, int arrayIndex)
  {
   throw new NotImplementedException();
  }

  public int Count
  {
   get { return list.Count; }
  }

  public bool IsReadOnly
  {
   get { return false; }
  }

  public bool Remove(T item)
  {
   throw new NotImplementedException();
  }

  public IEnumerator<T> GetEnumerator()
  {
   return list.GetEnumerator();
  }

  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  {
   return list.GetEnumerator();
  }
  #endregion 
 }<br/><br/> public class CustomSortEventArgs<T> : EventArgs<br/> {<br/>  public Comparison<T> Comparaison { get; set; }<br/>  public CustomSortEventArgs(Comparison<T> comparaison)<br/>  {<br/>   Comparaison = comparaison;<br/>  }<br/> }




This first class will sort the entier collection when a new item arrived. This class can do the job for the litteral objects like the integer for example as well as  composed types.
To test this staff you just create a console application and add this class then in the main method  add this code

MyArray<int> myarray = new MyArray<int>();
 myarray.Add(-12);
 myarray.Add(23);
 myarray.Add(5);

 foreach (var item in myarray)
 {
 Console.WriteLine(item);
 }

and then fire the application. This is for the simple and litteral type. In the other hand and for the complex type I provided a delegate property which is named Comparaison in MyArray class. You just write your custom comparaison method and add it to that delegate. To explain more let consider this custom class

public class BerberKing
 {
 public string KingName { get; set; }
 public byte DateOfRule { get; set; }
 public override string ToString()
 {
 return string.Format(" Name {0}, Date of rule {1} BC",
 KingName,
 DateOfRule.ToString());
 }
 }


This class will represent the berber kings of Tamazgha(North Africa) and the deal will be sorting the collection of the berber kings according to their date of rule (Descending from the more older to the less older).
To do that you write down a custom method that compares the kings in the program class

static int ComparaisonMethod(BerberKing king1, BerberKing king2)
 {
 if (king1.DateOfRule>king2.DateOfRule)
 {
 return -1;
 }
 else if (king1.DateOfRule < king2.DateOfRule)
 {
 return 1;
 }
 else
  {
 return 0;
  }
 }


And then in the main method you add this code

static void Main(string[] args)
 {
 BerberKing gaia = new BerberKing { KingName = "GAIA", DateOfRule = 238 };
 BerberKing masnsn = new BerberKing { KingName = "MASNSN", DateOfRule = 206 };
 BerberKing missipsa = new BerberKing { KingName = "MISSIPSA", DateOfRule = 148 };

 MyArray<BerberKing> collection = new MyArray<BerberKing>();
 collection.Comparaison = new Comparison<BerberKing>(ComparaisonMethod);
 collection.Add(masnsn);
 collection.Add(gaia);
 collection.Add(missipsa);

 foreach (BerberKing item in collection)
 {
 Console.WriteLine(item.ToString());
 }

 

 Console.Read();
 }

Relative source in WPF

A lot of people are getting confused when they try to use relative sources in a binding context. So for more details about what the relative source can do I dedicate this article

1. Mode Self:

Imagine this case, a rectangle that we want that its height is always equal to its width, a square let's say. We can do this using the element name

<Rectangle Fill="Red" Name="rectangle"
                    Height="100" Stroke="Black"
                    Canvas.Top="100" Canvas.Left="100"
                    Width="{Binding ElementName=rectangle,
                    Path=Height}"/>

But in this above case we are obliged to indicate the name of the binding object, namely the rectangle. We can reach the same purpose differently using the RelativeSource

<Rectangle Fill="Red" Height="100"
                   Stroke="Black"
                   Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Height}"/>

For that case we are not obliged to mention the name of the binding object and the Width will be always equal to the Height whenever the height is changed.

If you want to parameter the Width to be the half of the height then you can do this by adding a converter to the Binding markup extension.
Let's imagine another case now:

 <TextBlock Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Parent.ActualWidth}"/>

The above case is used to tie a given property of a given element to one of its direct parent ones as this element holds a property that is called Parent. This leads us to another relative source mode which is the FindAncestor one.

2. Mode FindAncestor

In this case, a property of a given element will be tied to one of its parents, Of Corse. The main difference with the above case is the fact that, it's up to you to determine the ancestor type and the ancestor rank in the hierarchy to tie the property. By the way try to play with this piece of XAML

<Canvas Name="Parent0">
        <Border Name="Parent1"
                 Width="{Binding RelativeSource={RelativeSource Self},
                 Path=Parent.ActualWidth}"
                 Height="{Binding RelativeSource={RelativeSource Self},
                 Path=Parent.ActualHeight}">
            <Canvas Name="Parent2">
                <Border Name="Parent3"
                Width="{Binding RelativeSource={RelativeSource Self},
               Path=Parent.ActualWidth}"
               Height="{Binding RelativeSource={RelativeSource Self},
                  Path=Parent.ActualHeight}">
                   <Canvas Name="Parent4">
                   <
TextBlock FontSize="16"
                   Margin="5" Text="Display the name of the ancestor"/>
                   <TextBlock FontSize="16"
                     Margin="50"
                Text="{Binding RelativeSource={RelativeSource 
                           FindAncestor,
                          
AncestorType={x:Type Border},
                           AncestorLevel=2},Path=Name}"
                           Width="200"/>
                    </Canvas>
                </Border>
            </Canvas>
        </Border>
    </Canvas>

The above situation is of two TextBlock elements those are embedded within a series of borders and canvas elements those represent their hierarchical parents. The second TextBlock will display the name of the given parent at the relative source level.

So try to change AncestorLevel=2 to AncestorLevel=1 and see what happens. Then try to change the type of the ancestor from AncestorType=Border to AncestorType=Canvas and see what's happens.

The displayed text will change according to the Ancestor type and level. Then what's happen if the ancestor level is not suitable to the ancestor type? This is a good question, I know that you're about to ask it. The response is no exceptions will be thrown and nothings will be displayed at the TextBlock level.

3. TemplatedParent

This mode enables tie a given ControlTemplate property to a property of the control that the ControlTemplate is applied to. To well understand the issue here is an example bellow

<Window.Resources>
    <ControlTemplate x:Key="template">
            <Canvas>
                <Canvas.RenderTransform>
                    <RotateTransform Angle="20"/>
                    </Canvas.RenderTransform>
                <Ellipse Height="100" Width="150"
                     Fill="{Binding
                RelativeSource={RelativeSource TemplatedParent},
                Path=Background}">

                  </Ellipse>
                <ContentPresenter Margin="35"
                      Content
="{Binding RelativeSource={RelativeSource 
                      TemplatedParent
},Path=Content}"/>
            </Canvas>
        </ControlTemplate>
    </Window.Resources>
        <Canvas Name="Parent0">
        <Button   Margin="50"
                  Template
="{StaticResource template}" Height="0"
                  Canvas.Left
="0" Canvas.Top="0" Width="0">
            <TextBlock FontSize="22">Click me</TextBlock>
        </Button>
    </Canvas>

If I want to apply the properties of a given control to its control template then I can use the TemplatedParent mode. There is also a similar one to this markup extension which is the TemplateBinding which is a kind of short hand of the first one, but the TemplateBinding is evaluated at compile time at the contrast of the TemplatedParent which is evaluated just after the first run time. As you can remark in the bellow figure, the background and the content are applied from within the button to the control template.

WPFSource1.gif

4. PreviousData

This is the most ambiguous and the less used mode of the RelativeSource, I mean the PreviousData one. The PreviousData is used for particular cases. Its purpose is to tie the given property to another property with a particular assignment; I mean it assigns the previous value of the property to the bound one. In other word, if you have a TextBox that has a text property and another control that has a value property that holds data. Say that value is actually 5 and it was 3 just before. The 3 is assigned to the text property of the TextBox and not 5. This leads to the idea that this kind of RelativeSource is frequently used with the items controls.

To understand the phenomenon of the RelativeSource let's expose this sample. I will add an ItemsControl into the scene and I will aliment it from a custom collection

<Grid>
    <ItemsControl></ItemsControl>
</
Grid
>

This ItemsControl is alimented using this collection:

public class Items : ObservableCollection<Item>
    {
        public Items()
        {
            Add(new Item { Value = 80.23 });
            Add(new Item { Value = 126.17 });
            Add(new Item { Value = 130.21 });
            Add(new Item { Value = 115.28 });
            Add(new Item { Value = 131.21 });
            Add(new Item { Value = 135.22 });
            Add(new Item { Value = 120.27 });
            Add(new Item { Value = 110.25 });
            Add(new Item { Value = 90.20 });
        }
    }

It's an ObservableCollection of type Item that I had developed and that holds a simple property which is called Value, it is of type double.

 public class Item :INotifyPropertyChanged
    {
        private double _value;
        public double Value
        {
            get { return _value; }
            set { _value = value; OnPropertyChanged("Value"); }
        }
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
     protected void OnPropertyChanged(string PropertyName)
     {
       if (null != PropertyChanged)
       {
         PropertyChanged(this,
              new PropertyChangedEventArgs(PropertyName));
       }
    }
 }

Now, to bind the ItemsControl to the collection data, I will set the DataContext property of the whole window to the collection at the Window constructor level.
 public Window1()
        {
            InitializeComponent();
            this.DataContext = new Items();
        }
And then I'll specify the binding of the ItemsControl

ItemsControl ItemsSource="{Binding}" Margin="10"

Then the result will be like this. I mean not presentable.

WPFSource2.gif

Therefore, we have to apply some features to enhance the visual of that representation.

<ItemsControl ItemsSource="{Binding}" Margin="10">
        <ItemsControl.ItemsPanel>
           <ItemsPanelTemplate>
              <StackPanel Orientation="Horizontal"/>
           </ItemsPanelTemplate>
           </ItemsControl.ItemsPanel>
       <ItemsControl.ItemTemplate>
          <DataTemplate>
              <StackPanel>
             <Border CornerRadius="3" BorderThickness="3"
                Width
="80" Height="{Binding Value}"
                            Margin
="0,0,35,0" 
                            BorderBrush="Violet" 
                            Background="BlueViolet">
                            <TextBlock Text="{Binding Value}"
                               FontWeight
="bold"
                               VerticalAlignment
="Center"
                               HorizontalAlignment="Center" 
                               Foreground="Wheat">
                        <TextBlock.RenderTransform>
                  <TransformGroup>
                            <ScaleTransform ScaleY="-1"/>
                
</TransformGroup>
                  </TextBlock.RenderTransform>
                  </TextBlock>
             </Border>
         </StackPanel>
      </DataTemplate>
   </ItemsControl.ItemTemplate>
   <
ItemsControl.RenderTransform>
       <TransformGroup>
         <ScaleTransform ScaleY="-1"/>
         <TranslateTransform Y="250"/>
       </TransformGroup>
   </ItemsControl.RenderTransform>
 </ItemsControl>

Shortly, I will describe the above XAML. First, the ItemsPanel will arrange the items within an horizontal StackPanel for more information about the ItemsPanel please refer to this link

http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemspanel.aspx

Second, the DataTemplate is used to present the data as a border; the border height is bound to the Value of the item class to reflect the Values that the collection holds. The same border includes a TextBlock that displays the Value of the Item object.

For more information about te DateTemplate please refer to this MSDN link

http://msdn.microsoft.com/en-us/library/system.windows.datatemplate.aspx


The RenderTransform is used to emphasize the position of the items in the scene. For more information about transformation please refer to this MSDN link

http://msdn.microsoft.com/en-us/library/system.windows.media.transform.aspx

The result of the presentation will be as follow

WPFSource3.gif

Now, the main purpose of this demo is to show the characteristic of the RelativeSource.PreviousData mode.

The idea consists of adding a TextBox and tie the Text property to the Value of the previous border in the items' list. Something that seems to be as the bellow representation

WPFSource4.gif

As you can note, each TextBlock represents the previous value that the previous item holds. This is in fact the magic of the PreviousData of the RelativeSource mode.

The idea is to add the TextBlock to the DataTemplate as Follow

<TextBlock FontSize="14" FontWeight="bold" Margin="20"
            Text="{Binding RelativeSource={RelativeSource PreviousData},
                   Path=Value}">
                          <TextBlock.RenderTransform>
                              <ScaleTransform ScaleY="-1"/>
                          </TextBlock.RenderTransform>   
</TextBlock>

Then the whole picture will be

<Grid>
    <ItemsControl ItemsSource="{Binding}" Margin="10">
        <ItemsControl.RenderTransform>
            <TransformGroup>
                <ScaleTransform ScaleY="-1"/>
                <TranslateTransform Y="250"/>
            </TransformGroup>
        </ItemsControl.RenderTransform>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock FontSize="14" FontWeight="bold"
                           Margin
="20"
                           Text="{Binding
                           RelativeSource={RelativeSource PreviousData},
                                               Path
=Value}">
                      <TextBlock.RenderTransform>
                          <ScaleTransform ScaleY="-1"/>
                      </TextBlock.RenderTransform>   
                   
</TextBlock>
                    <Border CornerRadius="3" BorderThickness="3"
                           Width
="80" Height="{Binding Value}"
                           Margin
="0,0,35,0" 
                        BorderBrush="Violet" Background="BlueViolet">
                        <TextBlock Text="{Binding Value}"
                           FontWeight
="bold" VerticalAlignment="Center"
                                   HorizontalAlignment="Center"
                                   Foreground="Wheat">
                        <TextBlock.RenderTransform>
                            <TransformGroup>
                        <ScaleTransform ScaleY="-1"/>
                       
</TransformGroup>
                        </TextBlock.RenderTransform>
                        </TextBlock>
                    </Border>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</
Grid>