Wednesday, August 12, 2009

Trips&Ticks: Do you know how you can unsubscribe from anonymous method?

Anonymous Methods is a useful feature which we receive in Framework 2.0. It allows to easy pass a small code block as a delegate parameter (you can set a large block code but this code will be harmful because it is complex and isn't clear for perception). For example:

button1.Click += delegate
{
MessageBox.Show( "Anonymous" );
};
But I have one trouble. What can I do if I want to unsubscribe from event. Seems it is subscribed finally, isn't it?.. Noup! If we declare instance of delegate before define we can unsubscribe a event from this delegate in the code block. For example:
EventHandler handler = null;

handler = delegate
{
MessageBox.Show( "Anonymous" );
button2.Click -= handler;
};

button2.Click += handler;
So if we click on button1 we receive message box always. If we click on button2 we receive message box once.

Wednesday, July 29, 2009

LINQPad (new version) - nice tool that can help you to stady LINQ.

LINQPad is nice tool that can help you to study LINQ. I have read firs overview of this tool. Absence auto-complete grieves most people. Auto-complete is present in new version. This option requiring payment. IMHO: auto-complete is more detrimental than efficiency for studying (but very useful for work).
But I want say not about that. LINQPad is obtain other interesting feature. Author of this tool Joseph Albahari with your brother had written book "C# 3.0 in a Nutshell" and he added LINQ samples from this book to LINQPad. You can not only investigate different case moreover you can see how it look in lambda and IL code.


Investigate these samples in IL code should be very interesting ;)

Sunday, July 19, 2009

Do you know about LINQ that.. ?

Do you know about LINQ to SQL that attribute is more important than value? What is it mean? My friend have found interesting relation. He had written LINQ to SQL where he checked a column value to null but he was disappointed - it wasn't worked if it was need. He had null values in set but LINQ code didn't see they (He had written simple test code with foreach - it worked). After some investigate he has found that trouble in mapped data. Particular property was marked ColumnAttribute with set CanBeNull property false. So LINQ implicitly optimizes him code regards attribute's value (skips the check to null).
PS: It shows that we should be careful to small thing.. because small things can implicitly brings a big and strange problems.

Do you know about nested class that.. ?

Download source files - here

Do you know about nested class that you can make nested class as partial? Yep, You can do it. Exactly your main class should be partial too.

Tuesday, June 16, 2009

This whimsical binding. TwoWay Binding to DataContext. Binding in WPF part 3.

I often use Binding to DataContext. It is one of the main advantage of WPF. In most case I set custom class inherit of DependencyObject (for support DependencyProperty) and I have some like next code:

<StackPanel>
<TextBlock Text="{Binding Path=Id}" />
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=Surname}"/>
...
</StackPanel>


But sometime I set a simple type for example string. For this case I can implement next Binding:

<TextBlock Text="{Binding}" />

Note: Pay attention, when we bind directly to DataContext I have written a short form (only 'binding' keyword).

But when I try to implement TwoWay Binding to DataContext. I have exception - "Two-way binding requires Path or XPath.". It cannot set a value from somewhere because it doesn't know where it came from. I can easy fix it. For example property IsChecked of CheckBox has request TwoWay Binding in metadata. For this case I have written next code:

<CheckBox IsChecked="{Binding Path=DataContext, RelativeSource={RelativeSource Self}}">

It is not so graceful, but it works.

Tuesday, June 2, 2009

Trips&Ticks: Set custom presented view for enum's fields in WPF.

Download source files - here.
Download bin files - here.

How you know, Enum can have underlying type as byte, sbyte, short, ushort, int, uint, long, or ulong. Often and often we need to present a view of Enum's values in visual elements. Usually enum's name isn't smooth for human look. As I have said we can't set for example string as underlying type and apply it as presented view.. We can use converter inherit from IValueConverter but it isn't comfortably as we need to reimplement it each time when Enum's count or order will be changed. I have implemented a simple class inherits from Attribute for set human smooth presented view:

[AttributeUsage( AttributeTargets.Field )]
public class ViewEnumAttribute : Attribute
{
public ViewEnumAttribute( String view )
{
View = view;
}

public String View
{
get;
private set;
}
}


We set AttributeTargets as Field for restrict scope of our attribute. Use of attribute is very simple:

public enum MyEnum
{
[ViewEnum( "My View Value 1" )]
MyEnumValue1,
[ViewEnum( "My View Value 2" )]
MyEnumValue2,
[ViewEnum( "My View Value 3" )]
MyEnumValue3,
}


and we extract this value when it is need:

private static object GetEnumView( Type fieldType, string fieldName )
{
FieldInfo info = fieldType.GetField( fieldName );

if( null != info )
{
foreach( ViewEnumAttribute attribute in info.GetCustomAttributes( typeof( ViewEnumAttribute ), false ) )
{
return attribute.View;
}
}

return fieldName;
}


For more details of realization you can look in attached above source files.

Monday, May 18, 2009

Implementing support of own child/children in WPF control.

Download source files - here
Download bin files - here

The best way for use child/children in WPF is customize any control with property for child/children that inherit from Control (for example ContentControl or ItemsControl). Control has wide possibility of customizing through ControlTemplate. But sometime we want to have a specific behaviour of child/children (for example if we want to implement MDI container any other specific container). What should you do for implementing this behaviour? I will show major steps in sample of simple custom panel that is inherited from FrameworkElement.

  1. First of all you should add property according type that will be contain child/children. I use Children property in my sample. It is list of UIElement. I use ObservableCollection because I need to react to collection change.
  2. You should see to show child/children in your control, you should override int VisualChildrenCount and Visual GetVisualChild( int). These method and property should get value accordingly with child/children property (child/children's count and this/these element/s according to index).
  3. Your app can correct build now but still nothing shows in app when it is run. It is happened because child/children doesn't/don't know their size and position on parent. You should override Size MeasureOverride(Size) for pass size (and calculate DesiredSize in child) to child's element and Size ArrangeOverride(Size) for pass position on parent. When you run app again you can see child/children in your custom control. You should point out to sizes that are returned in these method, MeasureOverride's size says to parent DesiredSize of your custom control and ArrangeOverride says to parent square that were taken.
  4. Now you can see that your custom control is run correct, but when you try to interact with their child/children you can see that interact is fail. It is happened because child/children property isn't/aren't added to visual tree of your custom control. AddVisualChild(Visual) method helps you in this. The best way is realized this behavior in property changed method for child or collection changed method for children. Pay attention that property changed isn't called for default value for your child/children property. We have some other reason set null as default value, but I say below about it.
  5. If you test your custom control more careful you can observe that interaction isn't complete. Yeah, visual interaction you have already implemented, but logical isn't complete. How can you observe it? Easy, try to use attached and inherit properties or DataContext - they don't work. You should add child/children to logical tree of your custom control. AddLogicalChild(Object) helps. You can call this method together with AddVisualChild.
  6. Be careful, if you want to remove element from child/children you shouldn't remember that this element should be removed from visual tree and logical tree. RemoveVisualChild(Visual) and RemoveLogicalChild(Object) help you in this.
  7. Interaction works correct now, but you can see new trouble, if you add/remove child/children in run-time you can't see any visual effect until do any change of size in app. It is happen because your custom control knows nothing about this add/remove action. If you are implementing child you can add AffectsArrange and AffectsMeasure flag to metadata of child property, they mean that custom control should do arrange and measure after each property change. If you are implementing children you should call InvalidateVisual() after each collection change. Added/Removed item shows/disappears immediately now.
  8. If you want set child/children property through XAML you should explicitly set your child/children property. You can apply to your custom control attribute ContentPropertyAttribute. So you can implicitly set your child/children property.
  9. In point #4 I have promised to say why you can't set default value no null. Pay attention that Dependency property is static member of class, so refer of one default value is added to all instances of your custom class. So you should use type that inherit form ValueType as type of dependency property or reinitialize default value in constructor (You should chose second way:).
  10. My coworker have found interesting trouble with RightToLeft support. His custom control can correct support RightToLeft only after he overrides LogicalChildren property. I can't reproduce it, but want to inform about possible trouble and solution for it.
I have written detailed road map with explanations. If some details aren't clear you can download sample with source code (case with children is implemented there).
Good luck!