As most of you might know (I hope) it is unwise to call methods on a Control from a non-UI thread. This can cause all sorts of issues. Actually, I think in most cases .NET will throw and Exception. If you need to set a property on a Control this is how you would properly do it.

VB.NET

 Delegate Sub SetPropertyValueDelegate(ByVal obj As Object, ByVal val As Object, ByVal index As Object())

 

    Public Sub SetControlProperty(ByVal ctrl As Control, ByVal propName As String, ByVal val As Object)

        Dim propInfo As PropertyInfo = ctrl.[GetType]().GetProperty(propName)

        Dim propertyDelegate As [Delegate] = New SetPropertyValueDelegate(propInfo.SetValue)

        'index

        ctrl.Invoke(propertyDelegate, New Object(2) {ctrl, val, Nothing})

    End Sub

 

    Private Sub UpdateSent(ByVal item As String)

        _chat.AppendLine(item)

 

        If Me.SentTextBox.InvokeRequired Then

            ' This is a worker thread so delegate the task.

            SetControlProperty(SentTextBox, "Text", _chat.ToString())

        Else

            ' This is the UI thread so perform the task.

            Me.SentTextBox.Text = _chat.ToString()

        End If

 

 

    End Sub

C#

        delegate void SetPropertyValueDelegate(Object obj, Object val, Object[] index);

 

        public void SetControlProperty(Control ctrl, String propName, Object val)

        {

            PropertyInfo propInfo = ctrl.GetType().GetProperty(propName);

            Delegate propertyDelegate = new SetPropertyValueDelegate(propInfo.SetValue);

            ctrl.Invoke(propertyDelegate, new Object[3] { ctrl, val, /*index*/null });

        }

 

        private void UpdateSent(string item)

        {

            _chat.AppendLine(item);

 

            if (this.SentTextBox.InvokeRequired)

            {   // This is a worker thread so delegate the task.

                SetControlProperty(SentTextBox, "Text", _chat.ToString());

            }

            else

            {   // This is the UI thread so perform the task.      

                this.SentTextBox.Text = _chat.ToString();

            }

 

        }

UpdateSent is example code on how to use the code. Also, _chat is a StringBuilder object. This code is taken from a chat program I wrote at where I work.

Tip Submitted By: David McCarter


 
Categories: Csharp | VB.NET | WinForms

If you came to my talk at the OC .NET User group meeting today, below is a link to the presentation. Enjoy!

Why You Need .NET Coding Standards (2008)

Why You Need .NET Coding Standards-2008.pdf (941.06 KB)

Link to my book: http://www.cafepress.com/geekmusicart.165478704


 
Categories: Csharp | Defensive Programming | dotNetDave | VB.NET

Two new technologies, the Entity Framework (EF) and ADO.NET Data Services were released with .NET 3.5 SP1 in August 2008. These two major editions to the framework finally provide true data modeling and an easy way to send the data across a WCF service. Making programming the data tier much easier (kind of). Since these technologies are so new there is not a lot of good information out there and a lot of what you can find is a lot of "fluff"... not much "real world" solutions. Since I have been actively been using this where I work since it came out in a "real" project, I thought I would share what I have learned. This will be a living blog post, meaning that as I find things I will update it. So check back often.

One thing I should mention is that the project I am working on is converting VB6 code to C#. We use SQL Server 2005 with most all of the data access going through stored procedures. Most of the sp's I have seen so far are simple selects and inserts or selects based on a parameter. So these are ideal candidates for just letting the EF create the SQL dynamically.

Entity Framework

Design Considerations

When starting this project I chose to create an assembly just for the Entity Data Model's. This way, down the road it could easily be shared with another applications. I chose the naming scheme for the assembly of: MyCompay.Project.Data.Entities.dll (of course replace "MyCompany" and "Project" with your company name and project name). This works great since by default entity type access is public.

There is one caveat with this, when you configure your entities, connections are created in the app.config file that look like this:

<configuration>

  <connectionStrings><add name="MyEntities" connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=MyServer;Initial Catalog=MyApplicationDB;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" /></connectionStrings>

</configuration>

This issue is when you reference this assembly in your WCF project (see more below), you will need to move the connection strings information to the web.config file under the <system.web> section.

Creating Your Entity Data Model

When I first started going though the VB6 project, I searched for sp calls or dynamic sql. As I saw these statements I added the appropriate tables to my data model. This worked great until I found the last table that was actually "root" table for the application. For example a Customer table that has a primary key that most if not all other tables rely on. While the designer correctly created the relationships, they never seemed to work correctly. I kept getting errors. So always add the "root" table first when creating your data model.

ADO.NET Data Services

Design Considerations

With the project I'm working on, there are multiple assemblies that will end up needing to connect to the Data Service to retrieve data. Because of this and the need to pass around the same "proxy" object, I decided to wrap the Data Service proxy in a separate assembly. The naming scheme I used for the assembly is: MyCompay.MyProduct.Data.ServiceProxy.dll  (of course replace "MyCompany" and "Project" with your company name and project name). By default the proxy object created to the Data Service is public so it's easily used by any other assembly. Also, configuration is easy since the location of the service is defined in one place in this assemblies app.config file.

LINQ

With the Data Services, LINQ can be used to call the service. This is great for the programmer since there is no need to master REST. Your LINQ statement will be automagically turned into REST. But be forewarned that at this point LINQ does not support all of REST. So you can write your LINQ statement, it will seem correct, but nothing will come back from the service. Most of the time there will be no warning or Exception either. So, if you are not getting data back, look at your LINQ query.

Loading Data

Retrieving data from a data service using LINQ is really simple. In my class I declare:

MyEntities _serviceProxy = new MyEntities();

Client _client;

Then to load, simply do the following LINQ statement:

_client = (from cl in _serviceProxy.Clients where cl.ClientId == this.ClientId select cl).Single<Client>();

This performs a call to the Data Service and returns a single Client object using a REST query simular to this:

http://localhost:4437/Services/MyDataService.svc/Clients('1')

To load child objects simply code the following:

_serviceProxy.LoadProperty(_client, "Accounts");

 

_serviceProxy.LoadProperty(_client, "Categories");

Each of the LoadProperty methods above will create a call to the Data Service. These calls can be batched to reduce network traffic, but you will basically have to write the REST queries manually... something I have not tackled yet.

Data Joins

Joins are not supported in Data Services because they are not supported in REST. But if you need to join data to display it in a grid etc, you can do it like you would do it in EF. For it to work the data will have to be preloaded into memory from the Data Service. The join would look similar to this:

var data = (from a in _client.Accounts

            join ac in _client.Categories on a.CatagoryId equals ac.Id into cat

            from c in cat.DefaultIfEmpty()

            orderby a.Type, a.Number

            select new

            {

                a.Id,

                a.Department,

                a.Number,

                a.Description,

                a.Type,

                a.IsTaxable,

                a.IsActive,

                Code = c == null ? string.Empty : c.Code

            }).Distinct();

 

accountGridView.DataSource = data.ToArray();

In the code above, cat.DefaultIfEmpty() is very important because if there is no match between Account and Category, then no data at all will be returned! Then in the last line of the select, it's also important to check for null, since "c" could be null and will throw an exception if you try to access one of its properties.

Now that you have your data into the grid control (DataGridView) you are going to run into another problem... retrieving the data from the DataSource! Since the data has been loaded as an anonymous type it can't be converted back. Also, since I chose not to show the Id property in the grid, I simply can not look at the first column.

So in my case, I only want the Id value of the row the user clicked on, from there I can use LINQ to look up the Account and what ever else I need to display more detailed data etc. For this we are going to have to use reflection.

private void accountGridView_SelectionChanged(object sender, EventArgs e)

{

     var data = accountGridView.Rows[accountGridView.SelectedRows[0].Index].DataBoundItem;

     var propInfo = data.GetType().GetProperty("Id");

     var propValue = (Int32)propInfo.GetValue(data, null);

 

     LoadAccountDetail((from acc in _client.Accounts where acc.Id == propValue select acc).Single());

}

As you can see in the code above we are using reflection and GetProperty to retrieve the value for Id from the grid DataBoundItem which I then use in the LINQ statement to retrieve the Account object.

Updating Data

One of the great things about the Entity Framework is the built in state tracking. This make is really simple to update, insert and delete object (data) with a single method call. Unfortunately, as soon as you serialize an EF object across the wire using any service including ADO.NET Data Service, this tracking is gone for the most part. Though Microsoft has promised to make this better in upcoming releases, for now we have to do it a little more manually, but still is pretty easy. You just need to remember this when using objects coming from a Data Service.

To update an object, simply change it's properties and then do the following:

_serviceProxy.UpdateObject(currentAccount);

 

_serviceProxy.SaveChanges();

Calling SaveChanges will make a call to the DataService. You can make as many calls to UpdateObject, AddObject and DeleteObject as needed before the SaveChanges call.

Service Methods

What's Not Supported
  • Enum parameters: I wanted to do this to send back different data based on an enum parameter (just like I do in normal programming). This is a perfect job for service methods. Unfortunately, I was told by Microsoft that it's not supported in "this release". They did not indicate if it will be supported in a future release.

"Good" Resources


 
Categories: ADO.NET | Csharp | Entity Framework | LINQ | WCF

If you are coming to the San Diego .NET Developers Group meeting tonight I hope you will be their early for my talk titled "What’s New In VS 2008 SP1". Lots of new additions to this SP, not just bug fixes. Below is a link to the presentation.

VS2008Sp1.pdf (715.88 KB)
 
Categories: .NET | ADO.NET | AJAX | ASP.NET | Csharp | dotNetDave | Entity Framework | LINQ | MVC | Silverlight | VB.NET | VS.NET | WCF | WinForms | WPF

August 8, 2008
@ 09:00 AM

The link below takes you to the Microsoft Express products like Visual Basic Express 2008 and SQL Server Express 2008.

http://www.microsoft.com/express/


 
Categories: Csharp | Link | SQL Server | VB.NET

June 1, 2008
@ 08:55 AM
Code

I hope everyone in southern California is planning to attend this years SoCal Code Camp up at University California San Diego on 6/28 - 6/29. It's always a great time and lots of free training! I will also be selling a limited number of my latest book "David McCarter's .NET Coding Standards" at my sessions for $11, cheaper than the web site (no tax and shipping), please bring exact change.

I will be presenting the following sessions and I hope you will attend.

dotNetDave's .NET Utility Assembly (My First CodePlex Project)

10:15 AM - Sunday, June 29, 2008 - Location: 141

zip_icon.gif dotNetDaves .NET Utility Assembly1.zip (1.11 MB)

CodePlex site: http://www.codeplex.com/dotNetTipsUtility

Building Rich & Interactive Web Applications with ASP.NET AJAX Part 1

8:45 AM - Saturday, June 28, 2008 - Location: 129

zip_icon.gif Building Rich & Interactive Web Applications with ASP.NET AJAX.zip (1.83 MB)

Building Rich & Interactive Web Applications with ASP.NET AJAX Part 2 

12:15 PM - Saturday, June 28, 2008 - Location: 129

zip_icon.gif Building Rich & Interactive Web Applications with ASP.NET AJAX Part 2 - 20081.zip (1.82 MB)

Why You Need .NET Coding Standards (2008)

1:45 PM - Sunday, June 29, 2008 - Location: 127

zip_icon.gif Why You Need .NET Coding Standards-20081.zip (2.86 MB)

Pictures and Video

Fullerton Code Camp - JAN 2008

Pictures from This Years Code Camp:

Pictures from past SoCal Code Camps:

Video from past Code Camps:

 


 
Categories: .NET | AJAX | ASP.NET | Code Camp | Csharp | Defensive Programming | Development | dotNetDave | News | VB.NET

April 14, 2008
@ 09:34 AM
If you live in the San Diego area, dotNetDave (a.k.a. David McCarter) will be teaching a 6 week Fundamentals of the .NET Framework course at the University of California, San Diego Extension beginning on Thursday 5/14/2008 from 5:30pm to 10:00pm. For more information and to enroll, please click here.


 
Categories: .NET | Csharp | dotNetDave | VB.NET

January 18, 2008
@ 08:25 PM

I hope everyone in southern California is planning to attend this years SoCal Code Camp up at Cal State Fullerton on 1/26 -1/27. It's always a great time and lots of free training! My fav southern California band Killola will be playing again at the Geek dinner so make sure you arrive early on Saturday to grab one of the limited number of tickets available.

167020688v3_240x240_Front_Color-Black.jpg

I will be doing the following sessions and I hope you will attend.

dotNetDave's .NET Utility Assembly (My First CodePlex Project)

zip_icon.gif dotNetDaves .NET Utility Assembly.zip (614.15 KB)

Building Rich & Interactive Web Applications with ASP.NET AJAX Part 1

zip_icon.gif Building Rich & Interactive Web Applications with ASP.NET AJAX Part 1 - 2008.zip (1.39 MB)

Building Rich & Interactive Web Applications with ASP.NET AJAX Part 2 

zip_icon.gif Building Rich & Interactive Web Applications with ASP.NET AJAX Part 2 - 2008.zip (1.11 MB)

Why You Need .NET Coding Standards (2008)

zip_icon.gif Why You Need .NET Coding Standards-2008.zip (1.71 MB)

Pictures and Video

Fullerton Code Camp - JAN 2008

Pictures from This Years Code Camp:

Pictures from past SoCal Code Camps:

Video from past Code Camps:

 

 


 
Categories: .NET | AJAX | ASP.NET | Code Camp | Csharp | Development | dotNetDave | JavaScript | News | VB.NET

dotdetdave-head-50.jpgIf you live in the San Diego area, dotNetDave (a.k.a. David McCarter) will be teaching a 6 week Building Rich & Interactive Web Applications with ASP.NET AJAX course at the University of California, San Diego Extension beginning on Thursday 2/21/2008 from 5:30pm to 10:00pm. For more information and to enroll, please click here.


 
Categories: .NET | AJAX | ASP.NET | Csharp | dotNetDave | JavaScript | VB.NET

David McCarter's .NET Coding StandardThe second edition of this book (formerly VSDN Tips & Tricks .NET Coding Standards), is a consolidation of many of the .NET coding standards available today in one easy to read and understand book. It will guide any level of programmer or development department to greater productivity by providing the tools needed to write consistent, maintainable code.

The core of the book focuses on naming standards, how to order elements in classes, declaring methods, properties and much, much more. Code tips are even included to help you write better, error free applications. All code examples are shown in C# and VB.NET. I use this book just about
every day and I hope you will too.
-David McCarter

"David McCarter once again demonstrates his knack for pulling best practices into one cohesive unit with his new book. This book includes everything from how to set up your project to how to declare variables to how to use exception handling. It is a great place to start to build your own set of coding standards."
- Deborah Kurata 5/5/05

To order, go to: http://www.cafepress.com/geekmusicart.165478704


 
Categories: .NET | Books | Development | dotNetDave | News | VB.NET | Csharp

August 9, 2007
@ 12:03 PM

San Luis Obispo will be holding a code camp on September 22nd, 2007. I will be attending and presenting. For more info go to: http://www.centralcoastcodecamp.com/

Articles/News:

http://www.sanluisobispo.com/business/story/134783.html

Code Camp on KCOY

My sessions will be:

Building Rich & Interactive Web Applications with ASP.NET AJAX

Presentation: AjaxSession091807.zip (875.6 KB)

Code Example: AjaxExample.zip (703.12 KB)

Why You Need .NET Coding Standards

Presentation: StandardsSession.zip (1.6 MB)

Pictures from the event: http://www.flickr.com/photos/davidmccarter/tags/cccc/


 
Categories: AJAX | Csharp | Code Camp | Development | dotNetDave | News | VB.NET

August 9, 2007
@ 12:01 PM

Phoenix will be holding another code camp on September 15th, 2007. I will be attending and presenting. For more info go to: http://desertcodecamp.com/

My sessions will be:

Building Rich & Interactive Web Applications with ASP.NET AJAX

Presentation: AjaxSession.zip (1023.53 KB)

Code Example: AjaxExample.zip (703.12 KB)

Why You Need .NET Coding Standards

Presentation: StandardsSession.zip (1.6 MB)

 


 
Categories: AJAX | Csharp | Code Camp | Development | dotNetDave | News | VB.NET

To download go to: http://go.microsoft.com/?linkid=5559918

 


 
Categories: .NET | Csharp | dotNetDave | Link | VB.NET | XML

username = string.Format(@"{0}\{1}", System.Environment.UserDomainName, 
System.Environment.UserName);

 

Tip Submitted By: David McCarter


 
Categories: Csharp

January 8, 2004
@ 01:43 AM

Unfortunately to do so, it must rely on an exception to detect a invalid value which is a little bit of a performance hit.

public static bool IsCurrency(object value)
{
  bool returnValue = false;
  try
    {
      double check = double.Parse(value.ToString(), NumberStyles.Currency, 
NumberFormatInfo.CurrentInfo);
      returnValue = true;
    }
  catch
    {}
  return returnValue;
}

I would excpect this code to work in normal C# applications too.

Tip Submitted By: David McCarter


 
Categories: Csharp | Compact Framework

January 8, 2004
@ 01:40 AM

Unfortunately to do so, it must rely on an exception to detect a invalid value which is a little bit of a performance hit.

public static bool IsNumeric(object value) 
{ 
  bool returnValue = false;
  try
    {
      double check = double.Parse(value.ToString(), NumberStyles.Any, 
NumberFormatInfo.CurrentInfo);
      returnValue = true;
    }
  catch
    {}
  return returnValue;
}

I would think that this would also work in normal C# applications.

Tip Submitted By: David McCarter


 
Categories: Csharp | Compact Framework

November 6, 2003
@ 02:01 AM

If you call your form like this:

formMyForm formModal = new formMyForm();
formModal.ShowDialog():

Make sure you properly dispose of it like this:

formModal.Dispose();

Bug Submitted By: David McCarter


 
Categories: Csharp | Compact Framework | Bugs

November 6, 2003
@ 01:46 AM

It’s not as hard as you might think in .NET. In the code below, just send the text and the Font object that, for example, the TextBox is using.

public static int GetTextWidth(string dataText, Font dataFont)
{
  return Graphics.FromImage(new Bitmap(1,1)).MeasureString(dataText, dataFont).ToSize().Width;
}

Tip Submitted By: David McCarter


 
Categories: Csharp | WinForms

When I was putting data from a DataTable as shown in the code below:

DataView locationsView = new DataView(MyDataSet.Tables["locations"]);
locationsView.Sort = "name ASC";
lstLocations.ValueMember = "key";
lstLocations.DisplayMember = "name";
lstLocations.DataSource = locationsView;

I got a very strange result as seen below:

Once I set the Sorted property to False, it worked fine. Go figure.

Bug Submitted By: David McCarter


 
Categories: Bugs | Csharp | WinForms

It’s was told to me that this can never be shown to the client and further more the number can never be rounded (anyone ever see Office Space… sound familiar?).

So I went searching on how to do this in .NET. After many, many hours of searching and testing, I could not find any way in .NET to do this. Every function I found would always round the number! I found myself wishing for just a way to flip a switch to tell .NET to stop doing that. So I finally gave up and came up with a short function that will do what the client needs.

The ConvertDecimal function will simply return a decimal number with the desired decimal places with NO ROUNDING.

private decimal ConvertDecimal(decimal inputValue, int placesAfter)
  {
   System.Text.StringBuilder sb = new System.Text.StringBuilder();
   string tempCreditAmount = Convert.ToString(inputValue);
   string[] tempSplit = tempCreditAmount.Split(Convert.ToChar("."));
   if (tempSplit.GetLowerBound(0) == 0)
    sb.Append(tempSplit[0]);
   
   if (tempSplit.GetUpperBound(0) == 1)
   {
    sb.Append(".");
    sb.Append(tempSplit[1].Substring(0,placesAfter));
   }
   return Convert.ToDecimal(sb.ToString());
  
  }

 

Tip Submitted By: David McCarter


 
Categories: Csharp

When setting a string object to an empty string, I did a test and I found that doing this:

string ContentFieldName = String.Empty;

Is slightly faster than doing this:

string ContentFieldName = "";

Your results my vary 

 

Tip Submitted By: David McCarter


 
Categories: Csharp

In a project I'm working on, images are sent over from a web service or are sitting on the users disk... both in an xml format. It's easy enough to save anything as base64 encoded, but how do you get it back to an actual image object? It's a little tricky.

Lets say you have your base64 string in a variable already. Well while it was stored in the xml file it could have gotten some extra characters in it... namely empty spaces and "\r\n". We need to remove them first. Here is the function that will do it:

public string FixBase64ForImage(string Image)
{
   System.Text.StringBuilder sbText =
      new System.Text.StringBuilder(Image,Image.Length);
   sbText.Replace("\r\n", String.Empty);
   sbText.Replace(" ", String.Empty);
   return sbText.ToString();
}

Now that the string it cleaned up the steps are:

  1. Convert the base64 string into a byte array.
  2. Convert the byte array into an in memory stream.
  3. Then finally convert the byte array into an image. This is actually a two step process (on one line of code).

if (ImageText.Length > 0)
{
   Byte[] bitmapData = new Byte[ImageText.Length];
   bitmapData = Convert.FromBase64String(FixBase64ForImage
     (ImageText));
   System.IO.MemoryStream streamBitmap = new 
     System.IO.MemoryStream(bitmapData);
   Bitmap bitImage = new 
     Bitmap((Bitmap)Image.FromStream(streamBitmap));
}

That's all there is to it!

 

Tip Submitted By: David McCarter


 
Categories: Csharp