Binding Events in WPF Templates

6. April 2013 14:14 by Mrojas in   //  Tags: , , , ,   //   Comments (0)

Recently we come up with a situation during a migration
to WPF where we needed to create a control that used an
item template and we needed to bind the item template
control to a control.

WPF in general is a framework that has great support for MVVM.
The DataBinding is great, but what about binding events.
Well... I don't know why WPF does not have an out-of-the box support
for event binding.
The MVVM way to do this binding is to use Commanding (see ...), but
is not that natural.

In this post I will describe how we worked out a solution for binding
an event, in particular Click Event for controls defined in an ItemTemplate.

So, all this story started when we had an itemtemplate like:

<HierarchicalDataTemplate x:Key="
  CheckBoxTreeViewItemTemplate" 
  ItemsSource="{Binding Items, Mode=OneWay}" >
 <StackPanel Orientation="Horizontal">
  <Image Margin="2,0" Source="{Binding ImageSource, Mode=TwoWay}" />
     <CheckBox Focusable="False" IsChecked="{Binding IsChecked}" VerticalAlignment="Center"/>
     <ContentPresenter Content="{Binding Text, Mode=TwoWay}" Margin="2,0" />
 </StackPanel>
</HierarchicalDataTemplate>


The idea was to create a collection of CheckBoxTreeViewItem(s) and bind that
collection to a control like a TreeView.
We also had a restriction. We did not wanted to subclass the TreeView
or any other control.

Binding an Event to an ItemTemplate

Google took me to this post:

http://stackoverflow.com/questions/2974981/wpf-datatemplate-event-binding-to-object-function

This gave me a great guide on how to bind the event item.

The starting code for our item was:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Controls;

    public class CheckedTreeViewItem : ItemsControl, INotifyPropertyChanged
    {
        bool? _isChecked = false;
        string _imageSource = String.Empty;
        int _imageIndex = -1;

        public TreeView TreeView
        {
            get
            {
                if (this.Parent != null && this.Parent is TreeView)
                {
                    return this.Parent as TreeView;
                }
                else if (this.Parent != null && this.Parent is CheckedTreeViewItem)
                {
                    return ((CheckedTreeViewItem)this.Parent).TreeView;
                }
                else
                {
                    return null;
                }
            }
        }

        public string ImageSource
        {
            get { return _imageSource; }
            private set { _imageSource = value;}
        }

        public bool? IsChecked
        {
            get { return _isChecked; }
            set { this.SetIsChecked(value, true, true); }
        }

        public bool IsExpanded
        {
            get;
            set;
        }

        public string Text { get; set; }

        public string Key { get; set; }

        public int ImageIndex 
        {
            get
            {
                return _imageIndex;
            }
            set 
            {
                _imageIndex = value;
                if (_imageIndex >= 0)
                {
                    var imageList = UpgradeHelpers.VB6.WPF.ImageList.ImageListAttachedProperties.GetImageList(TreeView);
                    var extractedSource = ((Image)imageList.Items[_imageIndex]).Source;
     _imageSource = extractedSource.ToString();
                }
                else
                {
                    _imageSource = String.Empty;
                }
                
            }
        }

        public bool IsInitiallySelected { get; private set; }

        public event PropertyChangedEventHandler PropertyChanged;

        void SetIsChecked(bool? value, bool updateChildren, bool updateParent)
        {
            if (value == _isChecked)
                return;

            _isChecked = value;

            if (updateChildren && _isChecked.HasValue)
            {
                foreach (CheckedTreeViewItem node in this.Items)
                {
                    node.SetIsChecked(_isChecked, true, false);
                }
            }

            if (updateParent && this.Parent != null && this.Parent is CheckedTreeViewItem)
                ((CheckedTreeViewItem)this.Parent).VerifyCheckState();

            this.OnPropertyChanged("IsChecked");
        }

        protected void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }

        void VerifyCheckState()
        {
            bool? state = null;
            for (int i = 0; i < this.Items.Count; ++i)
            {
                bool? current = ((CheckedTreeViewItem)this.Items[i]).IsChecked;
                if (i == 0)
                {
                    state = current;
                }
                else if (state != current)
                {
                    state = null;
                    break;
                }
            }
            this.SetIsChecked(state, false, true);
        }

    }


I needed a property exposing a command, so we could bind a controls
Command to a ClickEventHandler. The event should be defined as an
attached event. Why? Because we wanted users of this item to be able
to define for example in the TreeView an event handler that will be
then assigned to all my checkboxes. So if a users clicks one of the
checkboxes this event will be called.

// This event uses the bubbling routing strategy
              public static readonly RoutedEvent CheckedEvent = EventManager.RegisterRoutedEvent(
                     "Checked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TreeView));
 
              public static void AddCheckedHandler(DependencyObject d, RoutedEventHandler handler)
              {
                     UIElement uie = d as UIElement;
                     if (uie != null)
                     {
                           uie.AddHandler(CheckedTreeViewItem.CheckedEvent, handler);
                     }
              }
              public static void RemoveCheckedHandler(DependencyObject d, RoutedEventHandler handler)
              {
                     UIElement uie = d as UIElement;
                     if (uie != null)
                     {
                           uie.RemoveHandler(CheckedTreeViewItem.CheckedEvent, handler);
                     }
              }
 }

From my item I could obtain a reference to container control, but how
 could I retrieve the RoutedEvent from my container control...

Getting RoutedEvents from a control

<I used this reference http://stackoverflow.com/questions/982709/removing-routed-event-handlers-through-reflection/15854140#15854140>
I was surprised of how difficult and tricky this was. But this is how I did it:

// Get the control's Type
  Type controlViewType = ((UIElement)control).GetType();
 
  // Dig out the undocumented (yes, I know, it's risky) EventHandlerStore
  // from the control's Type
  PropertyInfo EventHandlersStoreType =
  controlViewType.GetProperty("EventHandlersStore",
  BindingFlags.Instance | BindingFlags.NonPublic);
 
  // Get the actual "value" of the store, not just the reflected PropertyInfo
  Object EventHandlersStore = EventHandlersStoreType.GetValue(tree, null);
  var miGetRoutedEventHandlers = EventHandlersStore.GetType().GetMethod("GetRoutedEventHandlers", BindingFlags.Public | BindingFlags.Instance);
  RoutedEventHandlerInfo[] res = (RoutedEventHandlerInfo[])miGetRoutedEventHandlers.Invoke(EventHandlersStore, new object[] { CheckedTreeViewItem.CheckedEvent });

  
  After doing that I could get the methodinfo an invoke that code thru reflection.
  So invoking the code is tricky too. When controls are put on the designer,
  the event handler are usually added to the window or page. So to retrieve the target I
  need to do the following:
  
  

var parent = VisualTreeHelper.GetParent(control);
  while (!(control is Window) && !(control is Page))
  {
    parent = VisualTreeHelper.GetParent(parent);
  }

  With that I can create an action to call the event handler like this:
  
      _handler = () => {
                           res.First().Handler.Method.Invoke(parent, new object[] { control, new RoutedEventArgs() })

 
  
 
Now back to binding an event to a template item thu a Command 

I created a new class called like the one on the post:

public class BindToClickEventCommand : ICommand
    {
              private Action _handler;
 
              public ViewModelCommand(Control control)
              {
                    
                     // Get the control's Type
                     Type someTreeViewType = ((UIElement)control).GetType();
 
                     // Dig out the undocumented (yes, I know, it's risky) EventHandlerStore
                     // from the control's Type
                     PropertyInfo EventHandlersStoreType =
                                  someTreeViewType.GetProperty("EventHandlersStore",
                                  BindingFlags.Instance | BindingFlags.NonPublic);
 
                     // Get the actual "value" of the store, not just the reflected PropertyInfo
                     Object EventHandlersStore = EventHandlersStoreType.GetValue(control, null);
                     var mi= EventHandlersStore.GetType().GetMethod("GetRoutedEventHandlers", BindingFlags.Public | BindingFlags.Instance);
                     RoutedEventHandlerInfo[] res = (RoutedEventHandlerInfo[])mi.Invoke(EventHandlersStore, new object[] { CheckedTreeViewItem.CheckedEvent });
                     var parent = VisualTreeHelper.GetParent(control);
                     while (!(parent is Window))
                     {
                           parent = VisualTreeHelper.GetParent(parent);
                     }
 
 
                     _handler = () => {
                           res.First().Handler.Method.Invoke(parent, new object[] { control, new RoutedEventArgs() });
                     };
                    
              }
 
              #region ICommand Members
 
              public bool CanExecute(object parameter)
              {
                     return true;
              }
 
              public event EventHandler CanExecuteChanged;
 
              public void Execute(object parameter)
              {
                     _handler();
              }
 
              #endregion
       }


 

And I added a property to the CheckedTreeViewItem

public BindToClickEventCommand CheckedEvent
{
 get
 {
  return new BindToClickEventCommand(TreeView);
 }
}


And bind that property by changing my template to:

<HierarchicalDataTemplate x:Key="CheckBoxTreeViewItemTemplate" ItemsSource="{Binding Items, Mode=OneWay}" >
        <StackPanel Orientation="Horizontal">
            <Image Margin="2,0" Source="{Binding ImageSource, Mode=TwoWay}" />
                     <CheckBox Focusable="False" IsChecked="{Binding IsChecked}" VerticalAlignment="Center"
                                    Command="{Binding CheckedEvent}"/>
                     <ContentPresenter Content="{Binding Text, Mode=TwoWay}" Margin="2,0" />
        </StackPanel>
    </HierarchicalDataTemplate>


 
 
In the container control all that is needed is to add the attached event like

<TreeView ...    local:CheckBoxTreeViewItem.Checked="item_Checked"



 
Once we did that we achieved our purpose. It is not perfect,
but due to some of the restrictions this is how we achieved it.

Slow first Time in ASP.NET applications

19. March 2013 12:19 by Mrojas in   //  Tags: , , , , , ,   //   Comments (0)

Well, this is a recurrent topic with ASP.NET:Why is the first page load always so slowjQuery152032498610322363675_1363786231988?

I don't think there is a definite answer but I can think on some explanations:

  • ASP.NET applications by nature exhibit some degree of delay upon initial access to the site. This can be due to JIT compilation, caching, etc. 
  • Note that it is also a common effect on some sharepoint sites. 
  • Some people on StackExchange attribute this slowness to: " The IIS application pool is shut down after 30 minutes of inactivity. After that, when you make a request IIS basically has to start the website up again, which leads to the behavior you are describing. You can change the idle time of your website in iis though to avoid it." 
Workarounds
 
 
There are some workarounds for this situation:
 
For some years there has been a warmup script that you can use on pre-vs2010 apps:
 

ASP.NET Site Warm up on GitHub

 
And there is  even an IIS addin for that, the following blog provides some references about this addin:
 

ASP .NET Pre heating and the App Warmup Addin for IIS

 
These problem is so common that now in VS 2010 there is even an auto-start feature that you can use:

Auto Start Feature in ASP.NET 4

 
 I hope this links help and I'll add more explanations as I find them. Please feel free to comment.

VB6 Types (Structs) with Fixed Length Strings

24. February 2013 12:06 by Mrojas in   //  Tags: , , , , , , , , ,   //   Comments (0)

 

In VB6 the communication with backend services usually involves the definition of Types (or Structs) using fixed length strings.

VB6 provided language support for defining these data types. 

For example:
Public Type HostData     
	UserName       As String * 8
	PassWord       As String * 8
	FullName       As String * 50
End Type
Figure 1 Example of VB6 Type with Fixed Length Strings
There are some ways to model this structures in .NET using the FixedLengthString defined in Microsoft.VisualBasic.Compatibity. Here I will present another approach. This approach uses character arrays (char[]) to model this structures. Ok. Let’s get down to business. To model a vb6 type like the one in Figure 1, we will use this approach:
struct HostData
    {
        [DebuggerDisplay("{s(UserName)}")]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
        public char[] UserName;

        [DebuggerDisplay("{s(PassWord)}")]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        char[] PassWord;

        [DebuggerDisplay("{s(FullName)}")]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
        public char[] FullName;
        /// This method is used to provide a better display of
	 /// character arrays as strings on the debugger.
        string s(char[] array) { return new string(array); }

        public byte[] toByteArray() {    
           return StructsHelper.StructToByteArray(this);
        }

 public static explicit operator HostData(byte[] array)
        {
            return (HostData)StructsHelper.ByteArrayToStructure(array,typeof(HostData));
        }

        /// <summary>
        /// Constructor to initialize the char arrays that are used as fixed length strings
        /// Struct constructors must have at least one parameter.
        /// </summary>
        /// <param name="initFixedLengthStrings">if true will automatically init all fixed length char arrays according to the SizeConst property of the MarshalAs attribute</param>
        public HostData (bool initFixedLengthStrings=false)
        {
            UserName = null; 
            PassWord = null;
            FullName = null;
            if (initFixedLengthStrings)
            {
                StructsHelper.InitFixedStrings(GetType(), __makeref(this));
            }
        }
    }
Figure 2: Code of Example 1 in C#
 
So several tricks are used here, I will describe them:
 

First

All fixed length strings are declared as char[]. A MarshalAs attribute is applied to each field. Like this:
[MarshalAs(UnmanagedType.ByValArray, SizeConst=n)]
Where n is the number of characters in the fixed length strings. Note that character arrays must be initialized. However structs do not allow field initializers. So they will need to be initialized on a constructor.
 

Second

A DebuggerDisplay attribute 
[DebuggerDisplay("{s(<AttributeName>)}")]
is added to each field, just to make the developer experience. That makes that instead of showing this field as a character array it will be shown as a string.
This attribute uses a small helper function used s that just converts the character array to string.
 

Third

A constructor is added. Structs do not accept parameter-less constructors.
This struct receives a Boolean indicating whether you want to initialize the character array fields.
As a requirement character arrays fields should at least be initialized to null. Character arrays could have been initialized here but I opted to create a helper function. Why? Well I think it is better if this arrays are initialized using the SizeConst attribute. So if I want to change their size I do not have to update both the SizeConst and the constructor.
public static void InitFixedStrings(Type type,TypedReference reference)  
        {
            if (type.IsValueType && !type.IsPrimitive && !type.Namespace.StartsWith("System") && !type.IsEnum)
            {//This should be an struct
                foreach (var field in
                    type.GetFields(System.Reflection.BindingFlags.Instance |
                    System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic))
                {
                    
                    if (field.FieldType.IsArray && field.FieldType == typeof(char[]))
                    {
                        var attr = field.GetCustomAttributes(typeof(MarshalAsAttribute),false);
                        if (attr != null && attr.Length > 0)
                        {
                            MarshalAsAttribute maa = (MarshalAsAttribute)attr[0];
                            var constSize = maa.SizeConst;
                            if (constSize != -1)
                            {
                                var newValue = new char[constSize];
                                field.SetValueDirect(reference, newValue);
                            }
                        }
                    }
                }
            }
        }
 

Forth>

In VB6 the common approach is to use the StrConv and CopyMemory functions to copy memory to and from structs and send them as strings or event to copy data between structs of different types. To solve that utility methods have been created:
/// <summary>
        /// Takes a bytearray and uses it to create a struct of the given type
        /// and populate it with the data of the byte array.
        /// NOTE: this method only works withs Structs which have a fixed size
        /// </summary>
        /// <param name="bytearray"> The data that will be used to initialize the struct</param>
        /// <param name="type">The type of the expected struct</param>
        /// <returns>A new struct instance with its fields initialized with the bytes from bytearray</returns>
        public static object ByteArrayToStructure(byte[] bytearray, Type type)
        {
            int len = Marshal.SizeOf(type);
            IntPtr i = Marshal.AllocHGlobal(len);
            Marshal.Copy(bytearray, 0, i, len);
            var obj = Marshal.PtrToStructure(i,type);
            Marshal.FreeHGlobal(i);
            return obj;
        }

/// <summary>
        /// Returns the contents of an struct as a byte array.
        /// It only works with fixed length structs.
        /// </summary>
        /// <param name="obj">the struct that holds the data that will be returned in the byte array</param>
        /// <returns>A byte array with the contents of the struct</returns>
        public static byte[] StructToByteArray(this object obj)
        {

            int len = Marshal.SizeOf(obj);
            byte[] arr = new byte[len];
            IntPtr ptr = Marshal.AllocHGlobal(len);
            Marshal.StructureToPtr(obj, ptr, true);
            Marshal.Copy(ptr, arr, 0, len);
            Marshal.FreeHGlobal(ptr);
            return arr;

        }
With these utility methods you can then use your structs like this:
var hostData = new HostData (true);
var byteArray = UnicodeEncoding.Unicode.GetBytes(new String(' ', Marshal.SizeOf(typeof(HostData))));
hostData = (HostData)byteArray;

var size = Marshal.SizeOf(HostData);
var test = "helloworld";
test = test.PadRight(size, '*');
            
byteArray = UnicodeEncoding.Unicode.GetBytes(test);
hostData = (HostData)byteArray;
 

Fifth

And finally how to you easily get/set data from these structs? Very easy. We will add an extension method:
const string IF_VALUE_NOT_PROVIDED_THEN_RETURN_VALUE = "\0\0internal";
        /// <summary>
        /// This method is used to get/set the values of a char array as an string.
        /// It has been implemented in a way similar to that used in the jquery .val function.
        /// If called without parameters it will return the character array value as an string.
        /// If called with parameters will use the given string to set the character array value.
        /// If the given string is bigger that the character string the value is truncated
        /// </summary>
        /// <param name="array"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string val(this char[] array, String value = IF_VALUE_NOT_PROVIDED_THEN_RETURN_VALUE)
        {
            if (value == IF_VALUE_NOT_PROVIDED_THEN_RETURN_VALUE)
                return new string(array);
            else
            {
                var source = value.ToCharArray();
                Array.Copy(source, array, Math.Min(source.Length, array.Length));
                return value;
            }
        }
With that if you want to set a field you will do something like:
hostData.UserName.val(“Mauricio”)
And if you want to get the contents of the field you will do something like:
String username = hostData.UserName.val();
Well that’s all. Hope this helps

StructsHelpers.cs (5.93 kb)

Share session state between ASP classic and ASP.NET or missing ASP classic and ASP.NET

31. January 2013 19:10 by Mrojas in   //  Tags: , , , , , , , ,   //   Comments (0)

Today my good friend Jafet asked me: "What do you think about sharing ASP classic and ASP.NET state?". And I told him that there were some projects for helping in this task.

I will mention some of them here.

The first one is NSession. This project provides an implementation that allows you to use the ASP.NET state server in ASP classic. You do not have to change your ASP classic code.

"You need to instantiate one of the COM objects in your ASP classic page before it accesses session state, either:

set oSession = Server.CreateObject("NSession.Session")

or

set oSession = Server.CreateObject("NSession.ReadOnlySession")


If you instantiate NSession.Session, the session state in the session store will be transferred to the ASP Classic session dictionary, and an exclusive lock will be placed in the session store. You do not need to change your existing code that accesses the ASP Classic session object. When NSession.Session goes out of scope, it will save the ASP Classic session dictionary back to the session store and release the exclusive lock.
If you have done with the session state, you can release the lock early with

set oSession = Nothing


If you instantiate NSession.ReadOnlySession, the session state in the session store will be transferred to the ASP Classic session dictionary but no locks will be placed."

The second option is SessionService. This project provides a mechanism for sharing the state between ASP classic and ASP.NET by serializing state data to an SQL Server.  The project page provides detailed information on how to setup IIS, how it is used in both platforms.

 

And the third option is a very interesting one called ASPClassicCompiler. This is a great great project. It provides a mechanism for compiling the ASP classic to .NET. This project is now opensource and we need to thank Li Chen for it.

 

Great ideas can be implemented thanks to this source. For example Brian Ellis suggested using the VBScript engine to replace the  MSScript.OCX. Another great one is an implementation of an View Engine that can be used with MVC and which support ASP Classic.

I really like the ASPClassic project and will be posting some interesting examples soon (as soon as I finish watching some Dr. Who episodes and the last Fringe season :) ) 

Can I use Subversion just like I used Microsoft Visual SourceSafe

30. January 2013 12:11 by Mrojas in   //  Tags: , , , , , , ,   //   Comments (0)

Subversion is great and has many features, but sometimes (specially when merges can be complicated) you might want to switch to working as you did in Visual Sourcesafe where you were the only one that could modify certain file until you check out.

A very common question I get is "I just want to work with subversion as I did with Sourcesafe!! How can I do it?"

One way to do that is to use SVN Locking. 

Tortoise provides a great way to do that: see this page.

 

Figure 1: This is the dialog you get in tortoise with you right click a file and select GetLock


Figure 2: To check who has a lock on a file you right click and select Check for modifications

The input[type="date"] in Internet Explorer (IE) 9 and 10

30. January 2013 09:26 by Mrojas in   //  Tags: , , , , , , , , , , ,   //   Comments (0)

Well, yes yes. IE is becoming better and has more support for HTML5 features but... still a lot of things do not work.

And that is very normal, browser will start adopting HTML5 little by little.

In case you want to use HTML5 feature not supported by your browser (which usually will be IE) then use two things:

  • Feature Detection and
  • Polyfills.

Feature Detection is the ability to determine if an HTML5 feature is supported or not by our browser. A good library for that is Modernizr. What you can do with modernizr is detect if any feature that you need is not supported and if not then you can conditionally load some javascript libraries that will implement that feature. Those libraries are called Polyfills.

So for example if you want to use the <input type="date" /> tag in IE 10 you could use the jqueryui.com controls to provide a date picker.

Modernizr.load({
		test: Modernizr.inputtypes.date,
		nope: "js/jquery-ui.custom.js",
		callback: function() {
		  $("input[type=date]").datepicker();
		}
	  });
Figure 1: Modernize script to test is the date type is supported

 Modernizr tests is the feature is supported, optionally you can use the nope to indicate if there is a library that you wan t to load ONLY if the feature is not supported, and callback is code that will be called after the test and after loading the library.

 

And this is the screenshot:

 

Figure2: Screenshot of IE10 with date picker
 
 
This technique can be used for a lot of other features. A good (but a little old article about that can be found HERE)
 
I have uploaded some test code if you want to test this quickly.
 
 

DatePicker.zip (148.76 kb)

Subversion with Coldfusion and Adobe Dreamweaver CS5

30. January 2013 08:53 by Mrojas in   //  Tags: , , , , , ,   //   Comments (0)

I found two great articles about using Dreamweaver with Subversion.

Part 1 is an introduction to subversion, an some general concepts about code versioning

and

Part2 is about confuring DreamWeaver to work with Subversion. An important aspect here is the directions on how to setup the file comparison tool. This is very important because in Subversion it is normal to have conflicts, but working without a nice file comparison tool can be a nightmare.

A couple of good comparison tools: SmartSVN (I really like this one but is commercial, but try it, it is very good) and Meld (you can download a version for windows from https://code.google.com/p/meld-installer/)

 

 

MSMQ COM in CSharp

28. January 2013 15:52 by Mrojas in   //  Tags: , , , , , , , ,   //   Comments (0)

I have a development computer with Windows 8 and Visual Studio 2012, and I was planning on doing some tests with MSMQ. Everybody will tell you that you should just (in Visual Studio) open the references tab and add a COM reference to Microsoft Message Queue, but (yes there is always a but) the component was not present.

I looked for it in C:\Windows\System32 and C:\Windows\SysWOW64 and nothing there was nothing called mq*.tlb. So I found this thread in StackOverflow and it was pretty obvious :| I just had to go to Add Programs \ Turn on Windows Features and select it:

Figure 1. Adding MSMQ COM components

 

And after that I could find a file called C:\Windows\System32\mqoa30.tlb and added that reference.

VB6 Interop of Function with Array of User Defined Type (UDT)

27. January 2013 03:33 by Mrojas in   //  Tags: , , , , , , , , ,   //   Comments (0)

Well tonight while I was deleting some spam comments from my blog and watching Dr. Who with my wife, I found a rather interesting comment.

So the story was:

First there is a VB6 DLL that had a class called Class1 with code like the following:

public type emprecord 
name as string 
end type 

Public Sub Fn(T()as emprecord) 
 MsgBox "The silence is comming said Prisoner 0"
End Sub

When this little dll was called from a VB.NET big brother 

Dim test as new prj.class1   
Dim em(0) as prj.emprecord 'able to create it no problem 
em(0).name="hello" 
test.fn(em)  ' here gives error


An error ocurred... well this is not very document issue with the TLBIMP tool which creates the interop assemblies. See StackOverflow Answer. The workaround is to right click on your type library, select properties, and change Embed interop Types to false.

After that you will be able to call your function.




Pretty Print XML in Javascript

25. January 2013 12:20 by Mrojas in   //  Tags: , , ,   //   Comments (0)

I searched all over for a simple solution to pretty print xml with JavaScript. I saw several answers in StackOverflow, but I just wanted a straight answer that I could just paste on my page and voila! but no. I couldn't find one.

Some people suggested using Google Prettify and is fine but prettify does not handle indentation and I had to escape the < > characters in my xml, and I just wanted to embed the xml in the page and have javascript handle the rest.

For the indentation some people recommended another javascript called vkBeautify but I just wanted a quick snipped of how to do it, well in the end my friend Joseph and I just put together a quick sample.

It was very simple but I tought there should be a lot of people with something like that already done.

 

We embed our xml like this:

<script type="text/xml" id="xml2">
<data><test>10</test><test>20</test></data>
</script>

 

Indentation is handled with the vkBeautity.

var text = textToHtml(vkbeautify.xml(document.getElementById('xml2').innerHTML));

Then we needed a function to do the escaping for us:

var pr_amp = /&/g;
var pr_lt = /</g;
var pr_gt = />/g;
var pr_quot = /\"/g;
/** escapest html special characters to html. */
function textToHtml(str) {
return str.replace(pr_amp, '&')
.replace(pr_lt, '<')
.replace(pr_gt, '>');
};

And the rest is just using the google prettify:

<body onload="updateText(),prettyPrint()" bgcolor="white">
<pre class="prettyprint" id="xml">
</pre>
</body>
 

NOTE: this solution still has a problem with carriage returns. So indentation is yet to be fixed

 UPDATE: I have fixed the issue. For some reason the IE gets rid of the '\n' in the string. So your have to change them for a <BR>

function updateText() {
	   		var text = textToHtml(vkbeautify.xml(document.getElementById('xml2').innerHTML));
			var expr = new RegExp("\n","g")
	   		document.getElementById('xml').innerHTML=text.replace(expr,'<br>');
		}

 UPDATE2:

For IE you might need to add this after the doctype:

<!doctype html>
 <meta http-equiv="X-UA-Compatible" content="IE=Edge">

prettyxml.zip (26.35 kb)

prettyxml2.zip (27.49 kb)

Easy Deployment of Coldfusion Apps on the Cloud

24. January 2013 16:36 by Mrojas in   //  Tags: , , , ,   //   Comments (0)

There are now a lot of Cloud Offerings. Amazon, Azure and I also really like Jelastic!

Jelastic is a great hosting environment for Java and PHP, but can it be used for ColdFusion. Sure!!

They have a very nice guide: http://blog.jelastic.com/2012/02/07/the-easiest-way-to-deploy-coldfusion-to-the-cloud/

Can you do the same with Azure or Amazon. Sure.

For example see this guide: http://www.windowsazure.com/en-us/develop/java/tutorials/tomcat-on-a-virtual-machine/

Once you have a vm with java you just deploy the coldfusion EAR and that's all :)

 

VM's policies are too old to be run by this version

23. January 2013 20:46 by Mrojas in   //  Tags: , , , , , , , ,   //   Comments (0)

I don't know why but I took one virtual machine from my computer to a clients office and when I tried to open it with VMware 9 I started getting a strange error: "VM's policies are too old to be run by this version"

What was that?

Well, I don't know yet, but my workaround was:

 

1. Go to the directory with the Virtual Machine files

2. Find <vm>.vmpl file and rename it to donotuse <vm>.vmpl

3. Double click the <vm>.vmx file

4. It will fail indicating that a file was not found

5. Open the <vm>.vmx file with notepad.exe. Look for something like:

policy.vm.mvmtid = "52 32 e7 62 63 ea 0d 0d-3a 55 cd 4c 11 69 ee e6"
policy.vm.managedVMTemplate = "FALSE"
policy.vm.managedVM = "FALSE"

Erase those three lines.

5. Save the file

6. And voila I was now able to open my virtual machine :)

Connect to MS Access from C/C++/PHP

21. January 2013 11:51 by Mrojas in   //  Tags: , , , , , ,   //   Comments (0)

Again Access... hey Access was a great database.

So if you are using access and you are thinking in how to use it from PHP or from a C/C++ app then you should check 

mdbtools

Does it work on iOS, well there is a discussion about at (http://old.nabble.com/Port-libmdb-(mdb-tools)-for-iOS-td34282658.html)  but I think there might be some licensing issues.

If that is the case I would recommend writting your own version of mdbtools, Take a look at https://github.com/brianb/mdbtools/blob/master/HACKING for detail info about the file format.

Connect to MS Access from C/C++/PHP

21. January 2013 11:51 by Mrojas in   //  Tags: , , , , , ,   //   Comments (0)

Again Access... hey Access was a great database.

So if you are using access and you are thinking in how to use it from PHP or from a C/C++ app then you should check 

mdbtools

Does it work on iOS, well there is a discussion about at (http://old.nabble.com/Port-libmdb-(mdb-tools)-for-iOS-td34282658.html)  but I think there might be some licensing issues.

If that is the case I would recommend writting your own version of mdbtools, Take a look at https://github.com/brianb/mdbtools/blob/master/HACKING for detail info about the file format.

Connect to MS Access from Java

21. January 2013 11:13 by Mrojas in   //  Tags:   //   Comments (0)

This is not an scenario that I commonly find, but now with Android and with the spread of Linux base environments an devices you are just don't want to be limited to just one technology.

So I found this library which I found extremely useful and I can recommend: 

Jackcess

Connect to MS Access from Java

21. January 2013 11:13 by Mrojas in   //  Tags: , , , , ,   //   Comments (0)

This is not an scenario that I commonly find, but now with Android and with the spread of Linux base environments an devices you are just don't want to be limited to just one technology.

So I found this library which I found extremely useful and I can recommend: Jackcess

 

The following are some code samples from the Jackcess library

  • Displaying the contents of a table:
    System.out.println(Database.open(new File("my.mdb")).getTable("MyTable").display());
    
  • Iterating through the rows of a table:
    Table table = Database.open(new File("my.mdb")).getTable("MyTable");
    for(Map<String, Object> row : table) {
      System.out.println("Column 'a' has value: " + row.get("a"));
    }
    
  • Searching for a row with a specific column value:
    Map<String, Object> row = Cursor.findRow(table, Collections.singletonMap("a", "foo"));
    if(row != null) {
      System.out.println("Found row where 'a' == 'foo': " + row);
    } else {
      System.out.println("Could not find row where 'a' == 'foo'");
    }
    
  • Creating a new table and writing data into it:
    Database db = Database.create(new File("new.mdb"));
    Table newTable = new TableBuilder("NewTable")
      .addColumn(new ColumnBuilder("a")
                 .setSQLType(Types.INTEGER)
                 .toColumn())
      .addColumn(new ColumnBuilder("b")
                 .setSQLType(Types.VARCHAR)
                 .toColumn())
      .toTable(db);
    newTable.addRow(1, "foo");
    
  • Copying the contents of a JDBC ResultSet (e.g. from an external database) into a new table:
    Database.open(new File("my.mdb")).copyTable("Imported", resultSet);
  • Copying the contents of a CSV file into a new table:
    Database.open(new File("my.mdb")).importFile("Imported2", new File("my.csv"), ",");

Remember that if you want to use it android you use some tweaks:

"The following steps will make Jackcess compatible with the Android platform.

  • Set the system property "com.healthmarketscience.jackcess.brokenNio=true"
  • Set the system property "com.healthmarketscience.jackcess.resourcePath=/res/raw/"
  • Copy the *.txt, *.mdb, and *.accdb files from the "com/healthmarketscience/jackcess/" directory in the Jackcess jar to the "/res/raw" Android application directory.
  • Before executing any Jackcess code, set the current Thread's context classloader, e.g. "Thread.currentThread().setContextClassLoader(Database.class.getClassLoader())"."

Migrate MS Access to SQL Server Compact Edition

21. January 2013 01:10 by Mrojas in   //  Tags: , , , , , , , , , ,   //   Comments (0)

Visual Basic and Access were a great combination. They allowed the creation of small powerful apps, specially apps for data collection, or just applications that needed a small database that could run standalone.

A good option when you are upgrading your Access database and you do not need a centralized SQL Server (or that is just too much for your environment) is to migrate to other options like SQLite or SQL Server.

SQL Server has now  a lot of versions (SQL Server Compact 3.5, SQL Server Compact 4.0, SQL Server Express and now even SQL Server LocalDB) a good table that compares this databases feature by feature can be located here: http://erikej.blogspot.com/2011/01/comparison-of-sql-server-compact-4-and.html)

If what you need is to support a simple, small (less that 4G) standalone database then using SQL Server Compact edition might be for you.

The main version for SQL Compact as at the moment 3.5 and 4.0.

Moving from Access to SQL Compact is not hard. There are many third party tools some free some not: http://erikej.blogspot.com/2009/04/sql-compact-3rd-party-tools.html 

Primeworks tools are very easy to use, but you can also use the Microsoft SQL Server Assistant for Access (good links for this tools are in MSDN http://msdn.microsoft.com/en-us/library/hh313039.aspx and also the SSMA Blog http://blogs.msdn.com/b/ssma/)

 

SQL Server Compact uses the ADO.NET and OLE DB providers, and in many scenarios is just what you need. So take it as an option if you just need a replacement for MS Access

 

 

Move code from .vb to .Designer.vb

18. January 2013 16:00 by Mrojas in   //  Tags: , , , , , , , ,   //   Comments (0)

If you still have Visual Studio 2003 projects and you are just in the process of upgrading / modernizing them, then the following addin will be very helpful. Mike Meinz, took a very useful macro and package it as a VS 2012 addin

See: http://www.codeproject.com/Articles/528990/A-Visual-Studio-add-in-to-move-Windows-Forms-Desig

For us who each day move lots of code from Vb6 and VB.NET to MVVM. ASP.NET MVC, etc, this kind of tools become very handy.

 

 

 

 

Simplify app deployment in .NET

11. January 2013 01:51 by Mrojas in   //  Tags: , , , , , , , , , ,   //   Comments (0)

 

The web platform provides an excellent mechanism simplify your app distribution and deployment issues.  

There is no longer a need for CD-ROMs, or to send a computer technician to install the app on each client computer. Other related problems such as verifying that the client has the right application version, application dependencies and security can be simplified.  

When you modernize your legacy app with Mobilize.Net\Artinsoft you could take advantage of several options. In terms of application distribution\deployment thru web technologies or running your application inside a web browser we have several post describing different way of doing this.  
 

Using ClickOnce deployment over the web to simplify Windows Form Application deployment 

Embedding Windows Forms Applications directly in a WebBrowser  

Embedding Windows Forms Applications in a WebBrowser using XBAP  

Silverlight as a mechanism for simplification of application deployment  

WPF applications distribution on the browser using XBAP  

 

Use HTML5 deploy your applications everywhere 

WPF applications deployment on the browser using XBAP

11. January 2013 01:44 by Mrojas in   //  Tags: , , , ,   //   Comments (0)

WPF is great and powerful technology to create compelling Windows Desktop applications when you need a rich user interface. 

Artinsoft/Mobilize.NET provide tools and services that allows you to modernize your VB6, Windows Forms and Powebuilder apps to WPF. Once your applications are on WPF you can also benefit from features like XBAP... 

From Wikipedia: 

"XAML Browser Applications (XBAP, pronounced "ex-bap") are Windows Presentation Foundation (.xbap) applications that are hosted and run inside a web browser such asFirefox or Internet Explorer. Hosted applications run in a partial trust sandbox environment and are not given full access to the computer's resources like opening a new network connection or saving a file to the computer disk and not all WPF functionality is available. The hosted environment is intended to protect the computer from malicious applications; however it can also run in full trust mode by the client changing the permission." 

XBAP is in general a simplification of the Click Once deployment, but specifically for WPF applications. 

Categories