Tuesday, 17 June 2008

Using Windows Form Control in WPF

Interesting enough that WPF does not have DateTimePicker (or Calendar). So we have decided to use the Windows Form DateTimePicker for now (just for now). Using a Windows Form control in WPF is not hard at all. :)

First of all, add a Grid to wherever you want your control to be:

    <Grid Height="28" Margin="116,0,0,49"
Name="DateGrid" VerticalAlignment="Bottom"
HorizontalAlignment="Left" Width="195">
</Grid>

Then add References to System.Windows.Forms and WindowsFormsIntegration and using:

using System.Windows.Forms.Integration;
using System.Windows.Forms;

Now, in your Window/UserControl Loaded event handler, create the Windows Forms Control and add it to the grid - by first adding it to WindowsFormsHost.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowsFormsHost host = new WindowsFormsHost();
DateTimePicker dateTimePicker = new DateTimePicker();
dateTimePicker.Width = (int)this.DateGrid.Width;
host.Width = (int)this.DateGrid.Width;
host.Child = dateTimePicker;
this.DateGrid.Children.Add(host);
}

That's it!

Friday, 6 June 2008

Refactoring: LINQ and Lambda Examples

I had migrated a project from .NET 2.0 to .NET 3.5. Guess it's also a good time to test some simple LINQ and Lambda. :)

Example 1: Simple List<A> to List<B>

List<ItBase> items = new List<ItBase>();

List<DBEntityBase> entities = GetDBEntities(typeof(ItBase), ids);

foreach (DBEntityBase entity in entities)
items.Add((ItBase)entity);

becomes

List<ItBase> items = new List<ItBase>();

List<DBEntityBase> entities = GetDBEntities(typeof(ItBase), ids);

items = entities.ConvertAll<ItBase>(e => (ItBase)e);

Example 2: Return members of List<A> with conditions


List<Attachment> attachments = new List<Attachment>();
foreach (Attachment attachment in this)

{
if (attachment.AttachmentType == attachmentType)
attachments.Add(attachment);
}

return attachments;
becomes

List<Attachment> attachments = new List<Attachment>();

return attachments.FindAll(a => a.AttachmentType == attachmentType);

Example 3: from array of int (index) returns List<Y> objects
List<ItBase> items = new List<ItBase>();

foreach (int id in ids)

{
items.Add(this[id]);
}

return items;
becomes

List<ItBase> items = new List<ItBase>();

items.AddRange(from i in ids select this[i]);
return items;

Example 4: From List<A> to List<B> but A and B are not inherited classes

List<User> users = new List<User>();

foreach (UserData userData in result)
{
User user = new User();
user.Email = userData.Email;
user.ID = userData.ID;
user.Name = userData.Name;
users.Add(user);
}
becomes

List<User> users = new List<User>();

users = result.ConvertAll<User>(r =>
new User
{
Email = r.Email,
ID = r.ID,
Name = r.Name,
}
);


WPF Example: Create UserControl and binding properties in a ListBox

see http://decav.com/blogs/andre/archive/2007/05/27/wpf-binding-to-properties-in-your-usercontrol-or-window.aspx

In order to bind the property, it needs to be a DependencyProperty, but not just that! You also need a control in XAML binding to your property. For example the following Control1 has a Message property:

XAML:

<UserControl x:Class="JSpike.Control1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Control1Name">

<Grid>
<TextBlock x:Name="textBlock" Text="{Binding ElementName=Control1Name, Path=Message}"
Width="100" Height="25" Background="Aquamarine"></TextBlock>
</Grid>
</UserControl>

CS:

namespace JSpike
{
/// <summary>
/// Interaction logic for Control1.xaml
/// </summary>
public partial class Control1 : UserControl
{
public Control1()
{
InitializeComponent();
}

public static DependencyProperty MessageProperty = DependencyProperty.Register(
"Message", typeof(string), typeof(Control1));


public string Message
{
get
{
return (string)GetValue(MessageProperty);
}
set
{
SetValue(MessageProperty, value);
}

}
}

Now I want to bind this in a ListBox on Window1.xaml:


XAML:

<Window x:Class="JSpike.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myCtrl="clr-namespace:JSpike"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<ObjectDataProvider x:Key="MyStringData"
ObjectType="{x:Type myCtrl:ListOfStuff}" MethodName="GetList" />

</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Source={StaticResource MyStringData}}"
Margin="0,36,78,0">
<ListBox.ItemTemplate>
<DataTemplate>
<myCtrl:Control1 Message="{Binding Path=.}" Height="37"
HorizontalAlignment="Left" VerticalAlignment="Top" Width="105"></myCtrl:Control1>
</DataTemplate>
</ListBox.ItemTemplate>

</ListBox>
</Grid>
</Window>

Class ListOfStuff is the data provider:

namespace JSpike
{
class ListOfStuff
{
public List<string> GetList()
{
List<string> list = new List<string>();
list.Add("Hello");
list.Add("Goodbye");
list.Add("Heya");
list.Add("Cya");
return list;
}
}
}

Result:


image