Apply function to LINQ query

•October 24, 2008 • Leave a Comment

In my last project i have been working with linq to do some cool stuff with objects. Like manipulating controls and specially doing any sort of filtering. I gotta say, linq is great for this. Many of you have in some point or another use a for each loop to filter the objects based on their properties; well, this all can be done easier using linq.

Ex. Closing windows using LinQ to object and expressions.  I am filtering all the windows for the current app and at the same time closing them. Calling the Count() function force the linq expression to apply the function and close the window.

private int closeWin(Window w)
{
 w.Close();
 return 0;
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{      
 System.Linq.Expressions.Expression<Func<Window, double?>> calc = (w) => closeWin(w);

 var childWindows = (from w in Application.Current.Windows.OfType<Window>()
      where w.Name != “mainWin”
      select calc.Compile().Invoke(w));
 var count = childWindows.Count();
 
}

Xceed single click checkbox

•October 24, 2008 • Leave a Comment

I apologize for not writting sooner,  I was far away from the wpf/silverlight world. Been stuck with a winform project. Thanks God is over.

The latest version of Xceed Datagrid has a lot of goodies. One of the is the single click checkbox.  If we are using a DataGridCollectionView as our dataitem, all we need to do to present the checkbox is declare the itemgrid property of type boolean.

<xceed:DataGridCollectionViewSource x:Key="dgGridSource"
                                         Source="{Binding}">
 <xceed:DataGridCollectionViewSource.ItemProperties>
                <xceed:DataGridItemProperty Name="Name" 
    IsReadOnly="True"  ValuePath="Name"    />
                <xceed:DataGridItemProperty Name="Age" 
    IsReadOnly="True" ValuePath="Age"   />
                <xceed:DataGridItemProperty Name="Male" 
    DataType="{x:Type System:Boolean}" 
    IsReadOnly="False" ValuePath="IsMale" />
 </xceed:DataGridCollectionViewSource.ItemProperties>
</xceed:DataGridCollectionViewSource>

 The importan line here is as the DataType attribute. DataType=”{x:Type System:Boolean}”.  In order to have access to the System namespace we need to add this reference to our control. 

 xmlns:System=”clr-namespace:System;assembly=mscorlib”

Then to get the single click editing we need to set the following attributes to the xceed datagrid. EditTrigger and CellEditorDisplayConditions.

<xceed:DataGridControl    x:Name="dgGrid"
                                ItemsSource="{Binding}"
                                EditTriggers="SingleClick"
                                CellEditorDisplayConditions="MouseOverCell"
                               >
</<xceed:DataGridControl>
That's it.  

Transparent WPF Window

•November 29, 2007 • Leave a Comment

 

For those who have played a bit with the exciting WPF windows, you may have noticed that the transparency of the form is related to the the windowstyle property. In other words, if you want to set the AllowTransparecy property to true, you would have to set the WindowStyle property to none.  One may wonder why does MS force us to do this,  well  in short;  Not all of the window is drawn by WPF. The title bar and border are still render by GDI+.  This means that any transformation or rendering possible on all the other objects in WPF are not possible on these two parts of the window. 

Therefore, in order to create a custom transparent window we must get rid of the border drawn by GDI+.  We can accomplish this in one line of code, however we must now handle manually the closing, resizing and dragging.

Xceed Datagrid Custom Cell Styling

•November 22, 2007 • 9 Comments

xceed_customcell1.jpg

As good as Xceed Datagrid is, it’s lacking some basic functionality or the documentation to find the workarounds.  We experience this when we tried to custom change the background of individuals cells base on their value.  A colleague of mine was working on this issue during the last week. After some extensive trial and error he came out with this solution.

Basically we need to register a Xceed.Wpf.DataGridControl.DataRow event,  Any event that gets called for all the DataRows in the DataGrid will suffice.   We decided to use the DataRow.SizeChangedEvent. 

EventManager.RegisterClassHandler(typeof(Xceed.Wpf.DataGrid.DataRow),
Xceed.Wpf.DataGrid.DataRow.SizeChangedEvent, new RoutedEventHandler(onDataRowSizeChanged));

We register a class handler event. This could be done inside the main constructor of your window. After that we implement the handler method as such:


void onDataRowSizeChanged(object sender, RoutedEventArgs e)
{
    Xceed.Wpf.DataGrid.DataRow dRow = (sender as Xceed.Wpf.DataGrid.DataRow);    //Getting the data value of the cells wanted:    DataRowView drView = dRow.DataContext as DataRowView;
    //Do our custom sytling base on data Values
    if (drView["equity"].ToString() == "0")
    {
       dRow.Cells["equity"].Background = Brushes.Red;
    }
    if (drView["balance"].ToString() == "0")
    {
       dRow.Cells["balance"].Background = Brushes.LightGreen;
    }
    if (drView["longvalue"].ToString() == "2282508")
    {
       dRow.Cells["longvalue"].Background = Brushes.Green;
       dRow.Cells["longvalue"].Foreground = Brushes.Blue;
    }
} Below is the xmal of the window: <Window x:Class="WPFPeformanceTest.XceedDataGrid"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"xmlns:xauto="clr-namespace:HelperClasses;assembly=HelperClasses"Title="Xceed DataGrid Custom Cell Style" Height="250" Width="800"WindowStyle="ThreeDBorderWindow"><Grid Name="dataGrid1"><xauto:XceedAutoFitColumnGrid Grid.Row="0" x:Name="accountsGrid" Margin="0,0,0,29" AutoCreateColumns="False"EditTriggers="BeginEditCommand,ActivationGesture" ><xcdg:DataGridControl.Columns><xcdg:Column FieldName="ACCOUNT" ReadOnly="True" Title="account" /><xcdg:Column FieldName="DEPT" ReadOnly="True" Title="dept" /> <xcdg:Column FieldName="longvalue" ReadOnly="True" Title="longvalue"/><xcdg:Column FieldName="balance" Title="balance" /><xcdg:Column FieldName="equity" ReadOnly="True" Title="equity"/><xcdg:Column FieldName="pending" Title="pending" /><xcdg:Column FieldName="reserves" ReadOnly="True" Title="reserves" /></xcdg:DataGridControl.Columns> </xauto:XceedAutoFitColumnGrid> <Label HorizontalAlignment="Left" x:Name="label1" VerticalAlignment="Bottom" Width="201.63" Height="23.2766666666667">Label</Label></Grid></Window>The end result can be viewed at the top of the page.

Autosize Columns XceedDataGrid WPF

•November 8, 2007 • Leave a Comment

Hello Everyone, I know its been a while, but to recent major events in my life i have been caught up.  Either way I am back.  Today I will show you a very useful and practical solution to autosize the columns in the XceedDataGrid fro wpf. 

 There is a property in the columns of the grid that returns the best fitted width of the columns.  Apparently this would be as simple as calling this function and setting the width of the column to the result of the fucntion; however there a couple of issues to consider. Otherwise, the function would return -1.

- The function must be called after the layout of the grid has been updated.  In order to do this we must called it before setting the itemsource of the DataGrid. 

Below there is a implementation of  custom class that inherits from XceedDataGrid and automatically autosized the columns:

public class XceedAutoFitColumnGrid : Xceed.Wpf.DataGrid.DataGridControl
  {
  private bool RunAutoFit = false;
public XceedAutoFitColumnGrid(): base()
  {
this.LayoutUpdated += new EventHandler(Grid_LayoutUpdated);

}
  private void Grid_LayoutUpdated(object sender, EventArgs e)
  {
  if (this.RunAutoFit)
  {
  AutoFit();
  this.RunAutoFit = false;
  }
  }

public void AutoFit()
  {
  foreach (Column col in this.Columns)
  {
  double fittedWidth = col.GetFittedWidth();
  if (fittedWidth > 0) col.Width = fittedWidth + 2;
  }
  }
  protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
  {
  UpdateLayout();
  base.OnItemsSourceChanged(oldValue, newValue);
  if (this.AutoCreateColumns) this.RunAutoFit = true;
  }

}

Generics – List Custom Sorting

•July 20, 2007 • Leave a Comment

Although the concept of templates is not quite new,  the particular implementation of templates done by Generics is quite nice.  I love working with them, they have proven to be very useful and flexible.  If you have not used them before, you should give it a try.

 For this shor example, we will covering one of the useful advantages of the Generic List< >

Custom Sorting
public class Student
{
//For Simplicit purposes these are public
public int age;
public string name;
public string id;

public Student(int _age, string _name, string _id)
{
age = _age;
name = _name;
id = _id;

}

public override string ToString()
{
string s = age + "\n" + name + "\n" + id + "\n";
return s;
}

}

Now we have the class, need to create and instanciate our list of students and add students


//Declare static since this is called from a console application
public static List studentList ;
public static void AddStudents()
{
Student student1 = new Student(20, "Bolton", "M");
Student student2 = new Student(20, "Abel", "M");
Student student3 = new Student(21, "Catherine", "1234");
Student student4 = new Student(21, "Catherine", "1111");
Student student5 = new Student(22, "Bart", "M");

studentList.Add(student1);
studentList.Add(student2);
studentList.Add(student3);

studentList.Add(student4);
studentList.Add(student5);

}

Now lets go unto sorting our list, this is the interesting part.

public static int SortStudents(Student leftStudent, Student rightStudent)
{
//sort first by Age
if (leftStudent.age > rightStudent.age)
return 1;
else if (leftStudent.age < rightStudent.age)
return -1;
else //if both students has the same age
{
//sort by name
if (leftStudent.name.CompareTo(rightStudent.name) != 0)
{
return leftStudent.name.CompareTo(rightStudent.name);
}
else //if both students has the same name and age, sort by id
{
if (leftStudent.id.CompareTo(rightStudent.id) != 0)
{
return leftStudent.id.CompareTo(rightStudent.id);
}
else
{
//in case both students to compare have identical values for all three properties
return 0;
}

}
}
}


The signature of this function is going to be similar for any object we would like to store in our List.
We’ll return an static int, and have will have two parameters of the type we are storing in our List; in this particular example since our list is a List of student we have both parameters of types students. Inside the body of the function we can do any comparison that we want to. Keeping in mind that we always need to return 0 in case both objects have the same value for all their properties. And that is, custom sorting of the objects store in any List.

Below the complete code for our console application example

namespace ListCustomSort
{
class Program
{
public static List studentList ;
static void Main(string[] args)
{
studentList = new List();
AddStudents();
DisplayStudents();

Console.WriteLine("Sorting students");

studentList.Sort(SortStudents);

DisplayStudents();

}

public static void DisplayStudents()
{
foreach(Student student in studentList)
{
Console.Write(student.ToString());
Console.WriteLine("-------------------");
}
}

public static void AddStudents()
{
Student student1 = new Student(20, "Bolton", "M");
Student student2 = new Student(20, "Abel", "M");
Student student3 = new Student(21, "Catherine", "1234");
Student student4 = new Student(21, "Catherine", "1111");
Student student5 = new Student(22, "Bart", "M");

studentList.Add(student1);
studentList.Add(student2);
studentList.Add(student3);
studentList.Add(student4);
studentList.Add(student5);

}

public static int SortStudents(Student leftStudent, Student rightStudent)
{
//sort first by Age
if (leftStudent.age > rightStudent.age)
return 1;
else if (leftStudent.age < rightStudent.age)
return -1;
else //if both students has the same age
{
//sort by name
if (leftStudent.name.CompareTo(rightStudent.name) != 0)
{
return leftStudent.name.CompareTo(rightStudent.name);
}
else //if both students has the same name and age, sort by id
{
if (leftStudent.id.CompareTo(rightStudent.id) != 0)
{
return leftStudent.id.CompareTo(rightStudent.id);
}
else
{
//in case both students to compare have identical values for all three properties
return 0;
}

}

}
}

}
}

Read and Write XML – Isolated Storage

•July 16, 2007 • Leave a Comment

Usually there is certain user related  info we would like to store in other place rather than the database.  For this task, we have several options, storing a a regular file, using the registry to save the settings, and so on.

The .Net framework also gives us the choice to use Isolated Storage,  basically the .Net handles the location of the file and its different for os user and for application.  I won’t go into the details of the Isolated Storage mechanism, but if you would like to have more info visit this link

Msdn Isolated Storage

For this example we would write the info of a DataSet to a xml file using Isolated Storage.
Writting part:
//Get the isolated store for this assembly
isf = IsolatedStorageFile.GetUserStoreForAssembly();
//Create a file at the top level of the store
isfStream = new IsolatedStorageFileStream("DB_Dump.xml", FileMode.OpenOrCreate, FileAccess.Write, isf);

//Create our streamwritter to write content to the file
StreamWriter sw = new StreamWriter(isfStream);

//assign a table to datatable
DataTable dt = ds.Tables[0];

//Write the content of the datatable to my xml file
dt.WriteXml(sw,XmlWriteMode.WriteSchema);

//it is very important to include the XmlWriteMode.WriteSchema,

//otherwise we'll get errors reading the xml file

Now for the reading part:
//Get the isolated store for this assembly
isf = IsolatedStorageFile.GetUserStoreForAssembly();
//Open a file at the top level of the store
isfStream = new IsolatedStorageFileStream("DB_Dump.xml", FileMode.Open, FileAccess.Read, isf);

//Our streamreader to read data
StreamReader sr = new StreamReader(isfStream);

//assign a table to datatable
DataTable dt = new DataTable();

dt.ReadXml(sr.ReadToEnd());

As you can see, its pretty straightforward. The only special consideration is setting the XmlWriteMode to Write Schema.

 
Follow

Get every new post delivered to your Inbox.