Feed Subscribe
Exception has been thrown by the target of an invocation.


Silverlight DataForm’s autogenerated fields send empty strings to database

by ondrejsv 28. March 2010 17:18

Silverlight Toolkit comes with a great control for quick building typical business application screens – DataForm, a sibling control to the DataGrid for showing and editing a single record. If you use its field autogeneration feature, you may be surprised when looking to the database after its first submit. All your ((n)var)char columns rendered as TextBoxes in the DataForm that had been empty have also empty string values in the database:

image

This is not what you usually want. If the field is left blank, I expect the database field be NULL instead of an empty string. So what to do to persuade the DataForm to send nulls in this case?

An IValueConverter, of course! First we define a suitable one which returns null when converting back an empty string:

public class SourceNullValueConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value == null ? "" : value.ToString(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (targetType != typeof(string)) return value; if (value == null) return null; return value.ToString() == "" ? null : value.ToString(); } }

Secondly, we need to force the DataForm to use this value converter instead of its own default DataFormToStringConverter. We do this by handling AutoGeneratingField event where we get the already built binding, copy it (by using CreateCopy extension method from the Silverlight Business Application template) and set our new value converter:

private void EmployeeForm_AutoGeneratingField(object sender, DataFormAutoGeneratingFieldEventArgs e) { if (e.Field.Content.GetType() == typeof(TextBox)) { Binding binding = e.Field.Content.GetBindingExpression(TextBox.TextProperty).ParentBinding.CreateCopy(); binding.Converter = new SourceNullValueConverter(); e.Field.Content.SetBinding(TextBox.TextProperty, binding); } }
image 

Case closed, Poirot!

kick it on DotNetKicks.com [digg]

Tags: ,

Easily migrate MySQL database into SQL Server

by ondrejsv 27. March 2010 20:11

If you want to migrate for whatever reason your MySQL database to SQL Server, forget all commercial tools or pesky DTS or SSIS packages! There’s a gem on the Microsoft SQL Server site called in the sterile marketing language Microsoft SQL Server Migration Assistant for MySQL or better SSMA for MySQL (currently CTP). Grab it from the Migration page.

image

Migration process has two steps – first you convert MySQL schema into corresponding SQL Server structures. You can either create tables directly on SQL Server instance or save the schema into file and run it later. In the second step you copy data. Everything in two clicks!

You can change some options regarding conversion between types and other and also you have choice to select just objects you are interested to migrate.

Two clicks and voila:

image

There are similar tools for migrating from Oracle, Sybase and Access on the Microsoft web site. Hopefully they give us a PostgreSQL one, too.

kick it on DotNetKicks.com [digg]

Tags: ,

How to: Create computed/custom properties for sample data in Blend/Sketchflow

by ondrejsv 14. March 2010 20:32

I blogged about sample data in Microsoft Blend/SketchFlow previously. SketchFlow is a great tool for rapidly building interactive screen prototypes. Sample data feature helps you to create plausible screen mocks quickly. I want to emphasize words interactive prototypes. Yes, user can click here and there and sees the entire “application flow”. Previously we mocked screens in HTML, had them rendered and sent this to our customers as a package full of JPEGs. Almost as a rule we had small disputes with customers who were arguing that they just cannot “grasp the application” from JPEGs. Now we can just publish a Silverlight prototype to our server and customers browse it throughout.

Hopefully I don’t need to note that logically connected screens should play together. Having double clicked a record in a datagrid on one screen and being redirected to another screen showing detailed information on this only record, data in fields should be the same (or related) to the record I clicked on the first screen. If you use sample data, it means that you should bind the first and second screen against the very same data source.

One problem I encountered is managing data derived from other fields in sample collection. Let’s say I have a customers collection with usual data like first name, last name and birth date. The first screen shows this list but I want to have only one column for customer name showing first and last name concatenated. I need them separated in my collection because the second “customer detail” screen would show them in separate text boxes. I could create a new string field and manually type in the full name but I am lazy to do such work and frankly have personal objections to do so. I prefer the way the full name field just computes itself. That way I can modify either name and full name updates automatically.

image

Double clicking on the Natasha row would bring me to the second screen with separate fields:

image

Fortunately, this task is not difficult. Your sample data collections are stored as XML files inside the SampleData folder in the XXXScreens project. For each such XML file, Blend generates a corresponding C# file with two ordinary class, one representing the collection and one the collection item (named Item):

image

public class Employees : System.ComponentModel.INotifyPropertyChanged { public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { if (this.PropertyChanged != null) { this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); } } public Employees() { try { System.Uri resourceUri = new System.Uri("/SilverlightPrototype_Derived.Screens;component/SampleData/Employees/Employees.xaml", System.UriKind.Relative); if (System.Windows.Application.GetResourceStream(resourceUri) != null) { System.Windows.Application.LoadComponent(this, resourceUri); } } catch (System.Exception) { } } private ItemCollection _Collection = new ItemCollection(); public ItemCollection Collection { get { return this._Collection; } } } public class Item : System.ComponentModel.INotifyPropertyChanged { public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { if (this.PropertyChanged != null) { this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); } } private string _LastName = string.Empty; public string LastName { get { return this._LastName; } set { if (this._LastName != value) { this._LastName = value; this.OnPropertyChanged("LastName"); } } } private string _FirstName = string.Empty; public string FirstName { get { return this._FirstName; } set { if (this._FirstName != value) { this._FirstName = value; this.OnPropertyChanged("FirstName"); } } } }

Pretty boring code. If only the Item class would be generated with the partial directive, we could add our own class with the FullName computed property.

Let’s start some hacking then. Close Blend, start your favorite text editor and open the file C:\Program Files\Microsoft Expression\Blend 3\Templates\en\SampleDataCode.cs. This is the template Blend uses for generating C# code from the sample data XML source file.

Change line 43 from:

public class COMPOSITE_TYPE : System.ComponentModel.INotifyPropertyChanged //CompositeTypeHeader - BEGIN

to:

public partial class COMPOSITE_TYPE : System.ComponentModel.INotifyPropertyChanged //CompositeTypeHeader - BEGIN

Now start Blend again, open your project, force Blend to regenerate the code file (by adding a new property and removing it immediately). If you open the sample data code file, you can notice that the Item class now has the partial keyword!

Add a new class, change the namespace to exactly math the one in the original code file and write your own partial class, like mine:

namespace Expression.Blend.SampleData.Employees { public partial class Item { public string FullName { get { return string.Format("{0} {1}", FirstName, LastName); } } } }

Job done! I may create a new bound column to my datagrid:


<data:DataGridTextColumn Header="Full Name" Binding="{Binding FullName}"/>

Note: Blend may not recognize your new properties, so you may need to write your bound fields in XAML yourself, not in the Blend UI.

kick it on DotNetKicks.com [digg]

Tags: ,