Wednesday, May 25, 2011

Data Binding improvements in WPF 4.0

In this post i will explain what are the new changes and improvements done in Data Binding in WPF 4.0

InputBinding

InputBinding was available in previous versions and the limitation was not able to bind Command property of InputBinding class. In WPF 4.0, InputBinding.Command property implemented as Dependency Property. Not only Command but KeyBinding.Key, KeyBinding.Modifiers, MouseBinding.MouseAction, InputBinding.CommandParameter and InputBinding.CommandTarget properties also implemented as Dependency Property so these all properties are now bindable.

Please have a look on below example of binding command property of InputBinding.

<Window x:Class="WPFTestApplication.InputBindingsImprovements"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFTestApplication"
        Title="Command Binding Improvements" Height="200" Width="200">
<Grid>
<Button Content="Hit Me!"
    Command="{Binding MyCommand}"           
    Height="30" Width="150">
    <Button.InputBindings>
        <KeyBinding
            Command="{Binding MyCommand}"
            Key="{Binding MyCommand.KeyGesture}"
            Modifiers="{Binding MyCommand.ModifierKey}" />
        <MouseBinding
            Command="{Binding MyCommand}"
            MouseAction="{Binding MyCommand.MouseActions}" />
    </Button.InputBindings>
</Button>
</Grid>
</Window>

CodeBehind

public partial class InputBindingsImprovements : Window
{
    public InputBindingsImprovements()
    {
        InitializeComponent();
        mycommand = new BaseCommand((str) => MessageBox.Show("Hello"));
        mycommand.KeyGesture = Key.H;
        mycommand.ModifierKey = ModifierKeys.Control;
        mycommand.MouseActions = MouseAction.RightClick;
        DataContext = this;
    }
    private BaseCommand mycommand;
    public BaseCommand MyCommand
    {
        get { return mycommand; }
    }

}
public class BaseCommand : ICommand
{
    Action<object> actionDelegate;
    public event EventHandler CanExecuteChanged;
    public BaseCommand(Action<object> myDelegateAction)
    {
        actionDelegate = myDelegateAction;
    }
    public void Execute(object action)
    {
        actionDelegate(action);
    }
    public bool CanExecute(object canexecute)
    {
        return true;
    }
    public Key KeyGesture { get; set; }
    public ModifierKeys ModifierKey { get; set; }
    public MouseAction MouseActions { get; set; }
}


Output
























In above example, I have bound MyCommand to Button so when user I click on button the MessageBox will appear. I have also bound the same Command with Key and Modifier to KeyBinding and MouseBinding. So when user Press Ctrl+H as well RightMouse Click on the Button the same Messagebox will appear.


Dynamic Object Binding

In WPF 4.0, you can databind dynamic (runtime known) properties. It supports binding to objects which implements IDynamicMetaObjectProvider or inherited from DynamicObject. DynamicObject class provides dynamic behavior at runtime. You can set or get members value by overriding TryGetMember or TrySetMember method.

<Window.Resources>
    <local:SimpleDynamicClass x:Key="MyInstance" />
</Window.Resources>
<StackPanel DataContext="{StaticResource MyInstance}">
    <Label Content="Enter anything:" />
    <TextBox Text="{Binding MyType}" Margin="5" Width="200"
                HorizontalAlignment="Left"/>
    <Button Content="Click Me!" Click="Button_Click"
            HorizontalAlignment="Left"
            Height="25" Width="100" Margin="5"/>
    <Label Name="ResultLabel" Margin="5" />
</StackPanel>

Code Behind
public class SimpleDynamicClass : DynamicObject
    {
        public string MyName;
        public override bool TryGetMember(GetMemberBinder binder, 
                                          out object result)

        {
            result = MyName;
            return true;
        }
        public override bool TrySetMember(SetMemberBinder binder,
                                          object value)
        {
            MyName = value.ToString();
            return true;
        }
    }

public partial class NewBindings : Window
    {
        public NewBindings()
        {
            InitializeComponent();
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            dynamic MyInstance = FindResource("MyInstance");
     ResultLabel.Content =  MyInstance.MyType;
        }
    }

Output
















In above example, I have created one class named SimpleDynamicClass derived from DynamicObject and bind its property with TextBox. On Button click I am retrieving the same instance value from resource and showing it in to the label.

Bindable Run Element

You can read about Bindable Run in my separate post here.


No comments:

Post a Comment