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.