Monday, April 11, 2011

FallbackValue vs. TargetNullValue

FallbackValue: Gets or sets the value when the binding is unable to return a value.
TargetNullValue: Gets or sets the value when the value of the source is null.

For instance, we have a label:

< Label Name="Label" Content="Value1" />

And a TextBox:
< TextBlock Text="{Binding ElementName=Label,Path=Content,FallbackValue=Value2,TargetNullValue=Value3}" />

We can test by doing the following operations respectively:

1.Do nothing,
2.Remove the Content="Value1"
3.Change Path=Content to Path=Content2

the text show in the Textbox will be:
Value1
Value3
Value2

Wednesday, April 6, 2011

Event in WinForm and WPF

Event is a member that enables a class to provide notification.

I. Review event in WinForm


Let's review event concept WinForm(or console, or Asp.net or any application which doesn't reference Presentation.Core assembly to support the concept of routed event) first:

1. EventHandler is a predefined delegate, it is the same as we define a delegate:

public delegate void Del(object,EventArgs);

It is also the same as Action< object, EventArgs>

EventHandler requires an object and an EventArgs as parameter.

2. We can define a custom event use any delegate type:

for example,we created a class called ExtendedButton:

public delegate void Del(int i);
public class ExtendedButton:System.Windows.Forms.Button
{
public event Del ValueSetted;
public event EventHandler Pushed;
public event Action MyMouseEntered;
}
3. Subscribe to the EventHandler Can also use Lambda Expression

for example:


ExtensionButton extbtn=new ExtensionButton();
extbtn.Pushed+=new EventHandler(myMethod);

public void myMethod(object s, EventArgs e)
{
//...Some code
}

We can also write:
extbtn.Pushed+=(s,e)=>//...Some code

4. Is event keyword optional?

The keyword event is important. Without event keyword, the member in the class will be treated as a field which is delegate type. for example the above code, we get the event keyword off:

public delegate void Del(int i);
public class ExtendedButton:System.Windows.Forms.Button
{
public Del ValueSetted;
public EventHandler Pushed;
public Action MyMouseEntered;
}

Then we can write code like this way:

ExtensionButton extbtn=new ExtensionButton();
extbtn.ValueSetted(5);
extbtn.Pushed(s,e);
extbtn.MyMousedEventered();

But when we add the keyword event, this make sure the event cannot be called outside of the owner class. Then this kind of call like extbtn.ValueSetted(5) will have compile error. The error message will be like:
"The event '' can only appear on the left side of += or -= (excepted used within the class '')"

5. How to invoke event outside of the Owner class?

We can add a method to the ExtensionButton class, for instance:
public class ExtendedButton:System.Windows.Forms.Button
{
public EventHandler Pushed;

public void RaisePushed()
{
if (Pushed != null)
Pushed(this, EventArgs.Empty);
}
}

Now we can invoke the event by:

ExtensionButton extbtn=new ExtensionButton();
extbtn.RaisePushed();

I have written the sample code here.

For C# 4.0, event mechanism for cross thread/synchronization is re written, see this
Link.



II. Event in WPF


WPF introduced routed events, which can be raised by multiple controls and handled by multiple handlers.

There are three type of routed events:
Direct Event
Bubbling Event
Tunneling Event

Monday, April 4, 2011

Another IoC container-Ninject

In the previous articles(Unity(1), Unity(2),Unity(3),Unity(4)), I wrote some notes on Unity Container. Recently I used another IoC container -Ninject, which seems a bit lighterr and also easy to use. So I am going to write a bit notes on Ninject.

Here is the Site for Ninject. And .Codeplex has great reference on this as well.

Reference the assembly Ninject.Core.

using Ninject.Core;

We have an interface:

public interface IMyService
{
void Dowork();
}

We have a Service class:

public class MyService:IMyService
{
public void Dowork()
{
//...Write some code;
}
}

Now we create a CustomModule class inherited from StandardModule

public class CustomModule: StandardModule
{
public override void Load()
{
Bind< IMyService>().To< MyService>();
}
}

Notice this CustomModule class do the type mapping.

Once you create modules, you load them into a container called the kernel.

Now in the application entry (if it is console, in Main function, if this is a Asp.Net application we should reference the Ninject.Framework.Web assembly, add a global.asax file, and let the Global class inherited from NinjectHttpApplication)

Sample code:

class Program
{
static void Main(string[] args)
{
CustomModule module=new CustomModule();
IKernel kernel=new StandardKernel(module);
}
}

For Asp.Net application,

public class Global:NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
CustomModule module=new CustomModule();
IKernel kernel=new StandardKernel(module);
return kernel;
}
}

When we want to resove the type from the container, it is also very simple:

For example, I have MyClass

public class MyClass
{
[Inject] //use the Inject attribute
public IMyService IMyService {get;set;}

protected void Method()
{
this.IMyService.Dowork();
//The method is called after resolving MyService from container
}
}

We will see use Ninject is simple, I will write some sample code on this later.

Some other points in Ninject is Contextual Binding, it is in the CustomModule class add conditions when do binding, it is also easy to understand, I am not going into details.