WPF 3D Controls Free Example

We just published 2 demo  projects:

Applications demonstrate major 3D controls functionality: animation, zooming, panning, and data binding.

To rotate the view hold mouse right button and move the mouse.

To zoom use mouse scroll wheel.

To pan hold mouse left button and move the mouse.

Click on any part to display a tool tip. Resize the window and see how the model reacts.

Screen shots:

Female anatomy demo project

Female anatomy demo project

Engine demo project

Thank you,

O.V.K.

How to get C# Enum description from value.

The following extension method retrieve enum value description.

The Enum:
public enum MyEnum
{
[Description("My Enum Item 1 Description")]
item1,

[Description("My Enum Item 2 Description")]

item2

}
Extension method:

/// <summary>

/// Retrieves DescriptionAttribute string for a given enum value

/// </summary>

/// <typeparam name=”T”>Enum type</typeparam>

/// <param name=”targetEnum”>Enum value</param>

/// <returns>String value of the DescriptionAttribute</returns>

public static string GetDescription<T>(this T targetEnum)

{

if (typeof(T).IsEnum == false)

throw new ArgumentOutOfRangeException(“T is not an enumeration”);

if (Enum.IsDefined(typeof(T), targetEnum))

{

var displayDescriptionAttributes =

typeof(T).GetField(targetEnum.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);

if (displayDescriptionAttributes.Length == 1)

return (displayDescriptionAttributes[0] as DescriptionAttribute).Description;

}

return String.Empty;

}

Example:

string result1 = MyEnum.item1. GetDescription(); // returns: “My Enum Item 1 Description”

string result2 = MyEnum.item2. GetDescription(); // returns: “My Enum Item 2 Description”

Thank you,

O.V.K.

Android IDE setup that works.

There is a very good step by step IDE installation guide published on official android development web site - http://developer.android.com/index.html

I followed  the instruction and … it did not work for me… So I had to do a small research to make it work.

The following guide describes android IDE setup that works. I was able to write, compile, and run applications without any problems.

  1. Recommended Dev Env: http://developer.android.com/sdk/requirements.html
  2. Install one of the following IDE: Recommended Eclipse IDE packages: Eclipse IDE for Java EE Developers, Eclipse IDE for Java Developers, Eclipse for RCP/Plug-in Developers, or Eclipse Classic (3.5.1+)  http://www.eclipse.org/downloads/ . I selected Eclipse Classic (3.5.1+)
  3. Unzip the file to c:\.  All the files will be under c:\eclipse folder. No installation needed. Run c:\eclipse\eclipse.exe to verify it is working.
  4. Download and install JDK: http://java.sun.com/javase/downloads/index.jsp I downloaded JDK 6 Update 17
  5. Install android SDK http://developer.android.com/sdk/installing.html
  • Download SDK http://developer.android.com/sdk/index.html
  • Unzip files to a folder
  • Optionally, you may want to add the location of the SDK’s primary tools directory to your system PATH. The primary tools/ directory is located at the root of the SDK folder. Adding tools to your path lets you run Android Debug Bridge (adb) and the other command line tools without needing to supply the full path to the tools directory.
    • On Windows, right-click on My Computer, and select Properties. Under the Advanced tab, hit the Environment Variables button, and in the dialog that comes up, double-click on Path (under System Variables). Add the full path to the tools/ directory to the path
  1. Install Android Development Tools plugin (The plug-in must have pointer to Android SDK. Please see the next step to setup Android plugin)
  2. Now modify your Eclipse preferences to point to the Android SDK directory:
  • Open eclipse.
  • Select Window > Preferences… to open the Preferences panel (Mac OS X: Eclipse > Preferences).
  • Select Android from the left panel.
  • For the SDK Location in the main panel, click Browse… and locate your downloaded SDK directory. (..\android-sdk-windows)
  • Click Apply, then OK.
  1. Window > Android SDK and AVD manager > Available packages > select all and install
  2. Done!
  3. Write first application:  http://developer.android.com/guide/developing/eclipse-adt.html
  4. Hello world application: http://developer.android.com/resources/tutorials/hello-world.html

Thank you,

http://npCompeteSolutions.com

XML Serializable Dictionary. Save/Load Dictionary to/from Human Readable XML File.

In this guide we are going to create a dictionary object that can be save/loaded to/from a human readable XML file.

A dictionary with 2 items

(“name1″, “value1″)
(“name2″, “value2″)

will be converted to the following XML file:

<?xml version="1.0" encoding="Windows-1252"?>
<properties>
  <add key="name1" value="value1" />
  <add key="name2" value="value2" />
</properties>

And vise versa – The XML file file will be converted to a dictionary with 2 items inside.

Click here to download a complete version of this application.

First, let’s create generic SerializableDictionary class:


namespace npCompete.XML
{
    [XmlRoot("dictionary")]
    public class SerializableDictionary<TKey, TValue>
        : Dictionary<TKey, TValue>, IXmlSerializable
    {
        #region IXmlSerializable Members

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {

            XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

            bool wasEmpty = reader.IsEmptyElement;
            reader.Read();


            while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
            {
                reader.ReadStartElement("item");
                reader.ReadStartElement("key");
                TKey key = (TKey)keySerializer.Deserialize(reader);
                reader.ReadEndElement();
                reader.ReadStartElement("value");
                TValue value = (TValue)valueSerializer.Deserialize(reader);
                reader.ReadEndElement();

                this.Add(key, value);

                reader.ReadEndElement();
                reader.MoveToContent();

            }

            reader.ReadEndElement();

        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

            foreach (TKey key in this.Keys)
            {
                writer.WriteStartElement("item");
                writer.WriteStartElement("key");
                keySerializer.Serialize(writer, key);
                writer.WriteEndElement();


                writer.WriteStartElement("value");
                TValue value = this[key];
                valueSerializer.Serialize(writer, value);
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
        }

        #endregion
    }
}

The class is straight forward, Is is straight forward – we inherited from a generic Dictionary<TKey, TValue> and implemented IXmlSerializable interface.

Now we need a generic XMLFile class to save/load any IXmlSerializable class to/from a file:


namespace npCompete.XML
{
    /// <summary>
    ///  Generic class to save/load an IXmlSerializable class.
    /// </summary>
    /// <typeparam name="TClass">IXmlSerializable class</typeparam>
    public class XMLFile<TClass> where TClass : IXmlSerializable
    {
        public void Save(TClass classInstance, string fileName)
        {
            XmlSerializer ser = new XmlSerializer(typeof(TClass));
            XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.Default);
            try
            {
                ser.Serialize(writer, classInstance);
            }
            catch (Exception ex)
            {
                throw new ApplicationException(
			"Exception while saving xml file to "
				+ fileName, ex);
            }
            finally
            {
                writer.Close();
            }
        }

        public TClass Load(string fileName)
        {
            TClass className = default(TClass);
            XmlSerializer ser = new XmlSerializer(typeof(TClass));

            XmlTextReader reader = new XmlTextReader(fileName);
            try
            {
                className = (TClass)ser.Deserialize(reader);
            }
            catch (Exception ex)
            {
                throw new ApplicationException(
				"Exception while reading xml file "
                                        + fileName, ex);
            }
            finally
            {
                reader.Close();
            }
            return className;
        }
    }
}

XMLFile class has 2 self explanatory methods: Save and Load with file name (full file path) and an IXmlSerializable class as parameters.
Let’s merry those 2 classes together and see the results.

    1             //SerializableDictionary test. Save dictionary to a file
    2             XMLFile<SerializableDictionary<string, string>> XMLFile =
    3                 new XMLFile<SerializableDictionary<string, string>>();
    4
    5             SerializableDictionary<string, string> serializableDictionaryToSave =
    6                 new SerializableDictionary<string, string>();
    7
    8             serializableDictionaryToSave.Add("name1", "value1");
    9             serializableDictionaryToSave.Add("name2", "value2");
   10
   11
   12             string fileName = @"TestSerializableDictionaryXMLFile.xml";
   13             XMLFile.Save(serializableDictionaryToSave, fileName);
   14
   15             //SerializableDictionary test. Load dictionary from a file
   16             SerializableDictionary<string, string> loadedSerializableDictionary =
   17                 new SerializableDictionary<string, string>();
   18             loadedSerializableDictionary = XMLFile.Load(fileName);

We created XMLFile (line 2-3), created  SerializableDictionary instance with some dictionary items (line 5-8) , save dictionary to a file using XMLFile.Save method (line 13), and load the dictionary back from the file (line 16-18).

Let’s see what the  TestSerializableDictionaryXMLFile.xml file look like:

<?xml version="1.0" encoding="Windows-1252"?>
<dictionary>
  <item>
    <key>
      <string>name1</string>
    </key>
    <value>
      <string>value1</string>
    </value>
  </item>
  <item>
    <key>
      <string>name2</string>
    </key>
    <value>
      <string>value2</string>
    </value>
  </item>
</dictionary>

Not quite what we would like to see.
We would like to serialize dictionary items into attributes, instead of nodes so the file would be more compact and easier to read.

We want XML look like this:

<?xml version="1.0" encoding="Windows-1252"?>
<properties>
  <add key="name1" value="value1" />
  <add key="name2" value="value2" />
</properties>

To fix this we need to change our IXmlSerializable implementation for the dictionary class.

I do not want to modify existing SerializableDictionary class, since it is very generic and might be useful in some scenarios.

Let’s create a new, more specialized class called XmlSettingsDictionary.
XmlSettingsDictionary is very similar to SerializableDictionary – we just tweek IXmlSerializable implementation a little bit:


namespace npCompete.XML
{

    [XmlRoot("properties")]
    public class XmlSettingsDictionary<TKey, TVal>
        : Dictionary<TKey, TVal>, IXmlSerializable
    {
        #region IXmlSerializable Members

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(XmlKeyValue<TKey, TVal>));

            reader.MoveToContent();
            while (!reader.EOF)
            {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "add")
                {
                    XmlKeyValue<TKey, TVal> entry = (XmlKeyValue<TKey, TVal>)serializer.Deserialize(reader);
                    this.Add(entry.Key, entry.Value);
                }
                else
                {
                    reader.Read();
                }
            }
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            foreach (TKey key in this.Keys)
            {
                writer.WriteStartElement("add");
                writer.WriteAttributeString("key", key.ToString());
                writer.WriteAttributeString("value", this[key].ToString());
                writer.WriteEndElement();
            }
        }


        #endregion
    }


    /// <summary>
    /// Helper struct to control XmlSerialization process.
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <typeparam name="V"></typeparam>
    [Serializable()]
    [XmlRoot("add")]
    public struct XmlKeyValue<K, V>
    {
        private K key;
        private V val;

        public XmlKeyValue(K name, V data)
        {
            this.key = name;
            this.val = data;
        }

        [XmlAttribute("key")]
        public K Key
        {
            get { return key; }
            set { key = value; }
        }

        [XmlAttribute("value")]
        public V Value
        {
            get { return val; }
            set { val = value; }
        }
    }
}

Run code to test this new class:

            //SerializableDictionary test. Save dictionary to a file
            XMLFile<SerializableDictionary<string, string>> XMLFile =
                new XMLFile<SerializableDictionary<string, string>>();

            SerializableDictionary<string, string> serializableDictionaryToSave =
                new SerializableDictionary<string, string>();

            serializableDictionaryToSave.Add("name1", "value1");
            serializableDictionaryToSave.Add("name2", "value2");


            string fileName = @"TestSerializableDictionaryXMLFile.xml";
            XMLFile.Save(serializableDictionaryToSave, fileName);

            //SerializableDictionary test. Load dictionary from a file
            SerializableDictionary<string, string> loadedSerializableDictionary =
                new SerializableDictionary<string, string>();
            loadedSerializableDictionary = XMLFile.Load(fileName);

This will produce TestSerializableDictionaryXMLFile.xml file:

<?xml version="1.0" encoding="Windows-1252"?>
<properties>
  <add key="name1" value="value1" />
  <add key="name2" value="value2" />
</properties>

Exactly, what we wanted. (At this moment, my 3 years old son would say “Good job, papa!”)

Click here to download a complete version of this application.

Hope it helps,

npCompeteSolutions.com

ASP.NET: CacheKeyDependency

During the development of our ASP.NET applications (http://www.npCompeteSolutions.com/) , We had a lot of problems with CacheKeyDependency. It simply didn’t work. The documentation in MSDN is definitely lacking. I couldn’t find any good information on the internet either.

After a lot of trial and error attempts I finally made it work. Let’s go through the following code to demonstrate the technique.

Add DataSource objects to the page.
Enable cache for the DataSource object:

…. asp:sqldatasource runat=”server” CacheKeyDependency=”MyTestKey”….

In code behind check Cache[CacheKeyDependency]. If it does not exists, create it:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {    //create CacheKeyDependency if it does not exists   
        if (Cache[SqlDataSource1.CacheKeyDependency] == null)
        {
            Cache[SqlDataSource1.CacheKeyDependency] = new object();
        }
    }
}

To refresh the cache use the following code:

 Cache[SqlDataSource1.CacheKeyDependency] = new object();

You can have one CacheKeyDependency key word for multiple DataSource objects, so when you run

Cache["MyTestKey"] = new object();

all the DataSource objects will have to renew the cache.

Thank you,
npCompeteSolutions.com

How to Force a ASP.NET page to use SSL (HTTPS)

The following sample code will force pages to use SSL (https) with ASP.NET:

//this is the current url 
System.Uri currentUrl = System.Web.HttpContext.Current.Request.Url;
//don't redirect if this is localhost
if (!currentUrl.IsLoopback)
{
    if (!currentUrl.Scheme.Equals(Uri.UriSchemeHttps,
        StringComparison.CurrentCultureIgnoreCase))
    {
        //build the secure uri 
        System.UriBuilder secureUrlBuilder = new UriBuilder(currentUrl);
        secureUrlBuilder.Scheme = Uri.UriSchemeHttps;
        //use the default port.         
        secureUrlBuilder.Port = -1;
        //redirect and end the response.        
        System.Web.HttpContext.Current.Response.Redirect(secureUrlBuilder.Uri.ToString());
    }
}

Thank you,

npCompeteSolutions.com

Log4net with SQL CE (Compact Edition)

The following guide shows how to use Sql Server CE (Compact Edition) to log your application events with Log4net.
Your SQL Server CE log table will look like this:

Result table image

Click here to download a complete version of this application.

Note: This tutorial references log4net version 1.2.10 and SQL Server CE version 3.5.

1. Create a new Console application solution.

2. Add to the project a reference to the [...]\bin\net\2.0\release\log4net.dll assembly in the log4net distribution.

3. Add to the project a reference to the SQL Server CE assembly: [...]\Program Files\Microsoft SQL Server Compact Edition\v3.5\Desktop\System.Data.SqlServerCe.Dll.

IMPORTANT! Make sure you set “Copy Local” to true for this dll.

4. Create logging database. Server Explorer – > Right click on Data Connections -> Add Connection -> Data Source should be “Microsoft SQL Server Compact 3.5 (.NET Framework Data Provider for Microsoft SQL Server Compact 3.5)” -> Click “Create” button -> Enter the new SQL Server Conpact database filename “LoggingDB.sdf” -> Click Ok -> Select “Yes” to continue with the blank password. – > Click Ok to close the “Add Connection” dialog.

5. Attach the LoggingDB.sdf file to the project (right click on the project name -> Add -> Existing Item -> Browse to LoggingDB.sdf file)

6. Set “Copy to Output Directory” propertyes to “Copy always” (right Click on LoggingDB.asf -> Properties -> Select “Copy Always” from the option list)

7. Create a Log table in the data base )Right click on Tables -> Create Table)

8. The table schema: (make sure you have NewID() as default value for ID field)

9. Add the following application configuration file (App.Config) to the console project:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" 
type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
  </configSections>
  <log4net>
    <root>
      <level value="DEBUG" />
      <appender-ref ref="SQLCEAppender" />
    </root>
    <appender name="SQLCEAppender" type="log4net.Appender.AdoNetAppender">
      <connectionType 
value="System.Data.SqlServerCe.SqlCeConnection, System.Data.SqlServerCe" />
      <connectionString value="Data Source='LoggingDB.sdf';" />
      <commandText 
value="INSERT INTO Log 
([Date],[Thread],[Level],[Logger],[Message],
[Exception], [UserName], [Custom]) 
VALUES 
(@log_date, @thread, @log_level, @logger, @message, 
@exception, @username, @custom)" />
      <parameter>
        <parameterName value="@log_date" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.RawUtcTimeStampLayout" />
      </parameter>
      <parameter>
        <parameterName value="@thread" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%thread" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@log_level" />
        <dbType value="String" />
        <size value="50" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%level" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@logger" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%logger" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@message" />
        <dbType value="String" />
        <size value="4000" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%message" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@exception" />
        <dbType value="String" />
        <size value="2000" />
        <layout type="log4net.Layout.ExceptionLayout" />
      </parameter>
      <parameter>
        <parameterName value="@username" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%username" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@custom" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{Custom}" />
        </layout>
      </parameter>
    </appender>
  </log4net>
</configuration>
10. Modify your Program.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using log4net.Config;
namespace ConsoleSQLCEExample
{
    class Program
    {
        private static log4net.ILog Log =
            log4net.LogManager.GetLogger(typeof(Program));
        static void Main(string[] args)
        {
            log4net.Config.XmlConfigurator.Configure();
            log4net.ThreadContext.Properties["Custom"] =
"This is a custom message";
            Log.Info("This is a info message");
            Log.Debug("This is a debug message");
            Log.Error("This is a error message");
            Log.Fatal("This is a fatal message");
            Log.Warn("This is a warning message");
        }
    }
}

11. Run the application.
12. Connect to LoggingDB.sdf in you \bin\Debug (or Releaase) folder (You can use Server Explorer -> Right click on Data Connetions -> Add Connection -> Click on “Browse” button and navigate to you \bin\debug\LoggingDB.sdf file)

13. Each log message produced by the utility routine will be saved to the Log table:

Coming Up

Next time we will add funtionality that sends the logg information over internet to a central server using Microsoft Sync Framework.
This way we will have multiple desktop application logs on a central place.

Thank you,
npCompeteSolutions.com