WPF
Exontrol.COM Software - Frequently Asked Questions
WPF.0:
In Microsoft WPF 32-bit you can use any of the following versions:
  • /WPF indicates the 32-bit edition of the /WPF assembly version

The application built using /WPF version runs on any Windows 32 or 64-bit machine.

In Microsoft WPF 64-bit you can use any of the following versions:

  • /WPF/64 indicates the 64-bit edition of the /WPF assembly version

The application built using /WPF/64 version runs on Windows 64-bit machine only. The application built using /WPF/64 version cannot run on Windows 32-bit machine.

If you want to use your application on 32 and 64-bit machines, you can go for:

  • /WPF/ANY indicates the 32 and 64-bit editions of the /WPF assembly version

Should I use a 32-bit or 64-bit version of the control?

WPF.1:
Run the DevStudio, and do the following:
  1. Right Click on the Toolbox
  2. Select the WPF Components tab page
  3. Click the Browse button
  4. Locate and select the wpf.exontrol.(name).dll component, for instance wpf.exontrol.exg2antt.dll
  5. Click OK.
This way, the Toolbox adds a new item that can be used to add the component to your project.
WPF.2:

The /WPF Component requires a runtime license key that's provided in the same registration e-mail you have received with your development license key. The runtime and development license keys are different.

For instance, your registration e-mail shows as follows:

Thanks for your purchase of the ExG2antt/WPF Retail!  To make use of your license for the ExG2antt/WPF Retail, you need to install the registered product with the key XXXX-XXXX-XXXX-XXXX (select the key, copy it to the clipboard, and then paste it to the "License Key" field). Your runtime license key is "your runtime license key"

The runtime license key should be passed to RuntimeKey property as follow:

VB.NET

	Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
		wpf.exontrol.EXG2ANTTLib.exg2antt.RuntimeKey = "your runtime license key"
	End Sub

C#

	public Window1()
	{
		wpf.exontrol.EXG2ANTTLib.exg2antt.RuntimeKey = "your runtime license key";
		InitializeComponent();
	}

or

	private void Window_Loaded(object sender, RoutedEventArgs e)
	{
		wpf.exontrol.EXG2ANTTLib.exg2antt.RuntimeKey = "your runtime license key";
	}

All this information can be found in redist.txt file that has been installed on your development machine.

WPF.3:
This problem is usually happen on Windows 64-bit machines, when only a single ( x32 or x64 ) development setup has been installed.

For instance, the Microsoft Visual Studio 2010 environment is a 32-bit process, even on a Windows 64-bit systems, so it runs on WOW64. It means, that when it is in design mode, the environment loads 32-bit files, so if you have a previously trial version installed, this will be shown. The registration message may appear on design mode, and when running not ( or reverse ). And this because usually, the project configuration is set on ANY CPU, so on a Windows 64-bit system the projects runs as 64-bit, so the 64-bit files are loaded. 

In conclusion, you need to install both setups that were provided at the purchasing time ( /WPF/ANY configuration ), on your development machine. 

See also:  "I get "cannot find file" for /NET or /WPF / "Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))" for /COM. What can I do?"
WPF.4:
This exception may occurs usually when you are initialization the component during window's constructor, instead after creating its handle. The component requires the Handle property to be not null ( IntPtr.Zero ), before adding or accessing any property or method of the control. You should call the initialization of the component during the Loaded or ContentRendered event of the window that hosts the component.

For instance, the following code calls the Init method during the New subroutine, which is wrong as at the time Init is called the Exg2antt1.Handle property is still 0. 

Class Window1 
    Public Sub New()
        InitializeComponent()
        Init()      ' WRONG
    End Sub

    Public Sub Init()
        Exg2antt1.Columns.Add("Def")
        Exg2antt1.Items.AddItem("Item")
    End Sub
End Class

Here's the good way of initialization the component: ( if you check the Exg2antt1.Handle property during the Windows_Loaded, you can see that it is not null )

Class Window1 
    Public Sub Init()
        Exg2antt1.Columns.Add("Def")
        Exg2antt1.Items.AddItem("Item")
    End Sub

    Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        Init()	' GOOD
    End Sub
End Class
The Init method is called during the Loaded event, which makes sure that the component's Handle is being created and so not null. You can use also the ContentRendered event, to initialize the component.
WPF.5:
This exception may occurs usually when you are initialization the component during window's constructor, instead after creating its handle. The component requires the Handle property to be not null ( IntPtr.Zero ), before adding or accessing any property or method of the control. You should call the initialization of the component during the LayoutUpdated event of the control that hosts the component, when the control's Handle property is not IntPtr.Zero.

For instance in VB.NET, let's say we need to show the control into an Expander control, so we would have a code like:

Imports wpf.exontrol.EXG2ANTTLib

Class Window1
    Dim expander As Expander = New Expander
    Dim Exg2antt1 As exg2antt = New exg2antt

    Public Sub New()
        InitializeComponent()

        expander.Content = exg2antt1
        Me.Content = expander

        Init()      ' WRONG

    End Sub

    Public Sub Init()
        Exg2antt1.Columns.Add("Def")
        Exg2antt1.Items.AddItem("Item")
    End Sub
End Class

You need to handle the LayoutUpdated event of the Expander component, and check when the control's Handle is being created as in the following sample

Imports wpf.exontrol.EXG2ANTTLib

Class Window1
    Dim expander As Expander = New Expander
    Dim Exg2antt1 As exg2antt = New exg2antt

    Public Sub New()
        InitializeComponent()

        expander.Content = Exg2antt1
        Me.Content = expander

        AddHandler expander.LayoutUpdated, AddressOf Me.OnLayoutChanged

    End Sub

    Private Sub OnLayoutChanged()
        With Exg2antt1
            If Not (.Handle = IntPtr.Zero) Then
                If (.Columns.Count = 0) Then
                    Init()	' GOOD
                End If
            End If
        End With
    End Sub

    Public Sub Init()
        Exg2antt1.Columns.Add("Def")
        Exg2antt1.Items.AddItem("Item")
    End Sub
End Class

The Init method is called during the LayoutUpdated event, when the component's Handle is being created and so not null.

For instance in C#, let's say we need to show the control into an Expander control, so we would have a code like:

using wpf.exontrol.EXG2ANTTLib;

public partial class Window1 : Window
{
    Expander expander = new Expander();
    exg2antt exg2antt1 = new exg2antt();

    public Window1()
    {
        InitializeComponent();

        expander.Content = exg2antt1;
        this.Content = expander;

        init(); // WRONG
    }

    private void init()
    {
        exg2antt1.Columns.Add("Def");
        exg2antt1.Items.AddItem("Item");
    }
}

You need to handle the LayoutUpdated event of the Expander component, and check when the control's Handle is being created as in the following sample

using wpf.exontrol.EXG2ANTTLib;

public partial class Window1 : Window
{
    Expander expander = new Expander();
    exg2antt exg2antt1 = new exg2antt();

    public Window1()
    {
        InitializeComponent();

        expander.Content = exg2antt1;
        this.Content = expander;

        expander.LayoutUpdated += new EventHandler(expander_LayoutUpdated);
    }

    void expander_LayoutUpdated(object sender, EventArgs e)
    {
        if (exg2antt1.Handle != IntPtr.Zero)
            if (exg2antt1.Columns.Count == 0)
                init(); // GOOD
    }

    private void init()
    {
        exg2antt1.Columns.Add("Def");
        exg2antt1.Items.AddItem("Item");
    }
}
The Init method is called during the LayoutUpdated event, when the component's Handle is being created and so not null.
WPF.6:
This error could appear when trying to add a handler for KeyUp, KeyDown, KeyPress, BeforeExpandItem, Edit, Change event ( or any other event that carries a parameter passed by reference ) from XAML editor. This error is generated by VS 2008, by ignoring the ref keyword for event definitions.

C#

When adding the KeyDown event from XAML the VS generates the handler as:

private void exg2antt1_KeyDown(object sender, short KeyCode, short Shift)
{
}

and when compiling you get: "error CS0123: No overload for 'exg2antt1_KeyDown' matches delegate 'wpf.exontrol.EXG2ANTTLib.exg2antt.KeyDownEventHandler'"

The error occurs because the ref keyword is missing from the event definition. So, replace the definition of the event as:

private void exg2antt1_KeyDown(object sender, ref short KeyCode, short Shift)
{
}

and the error is gone. 

VB/NET

When adding the KeyDown event from XAML the VS generates the handler as:

Private Sub Exg2antt1_KeyDown(ByVal sender As System.Object, ByVal KeyCode As System.Int16, ByVal Shift As System.Int16)
End Sub

and when compiling you get: "error BC31143: Method 'Private Sub Exg2antt1_KeyDown(sender As Object, KeyCode As Short, Shift As Short)' does not have a signature compatible with delegate 'Delegate Sub KeyDownEventHandler(sender As Object, ByRef KeyCode As Short, Shift As Short)'."

The error occurs because the parameter KeyCode is not generated with ByRef  keyword.  So, replace the definition of the event as:

Private Sub Exg2antt1_KeyDown(ByVal sender As System.Object, ByRef KeyCode As System.Int16, ByVal Shift As System.Int16)
End Sub

and the error is gone.

This error does not occur if you select the object and the event from the code editor, so it will add a new handler for selected event.
WPF.7:
In order to add print and print- preview capabilities for our /WPF component please follow the steps.
  • You need to download and install the exprint/net assembly ( at least version 5.1.0.4 ) 
  • Add a reference to your project to exontrol.exprint.dll ( Browse to system folder or control's sample folder where you can find the file exontrol.exprint.dll )
  • Declares and initializes a member exprint of  exontrol.EXPRINTLib.exprint type
  • At a click of a button, you can call the PrintExt / PrintExts to refer the control / controls to be printed, and right after you should call the Preview or DoPrint as in one of the following samples:

C#

exontrol.EXPRINTLib.exprint exprint = new exontrol.EXPRINTLib.exprint();

private void button1_Click(object sender, RoutedEventArgs e)
{
	exprint.PrintExt = exg2antt1;
	exprint.Preview();
}

or if you need to print multiple objects:

exontrol.EXPRINTLib.exprint exprint = new exontrol.EXPRINTLib.exprint();

private void button1_Click(object sender, RoutedEventArgs e)
{
	object[] objs = { exg2antt1, exg2antt2};
	exprint.PrintExts = objs;
	exprint.Preview();
}

VB/NET

Private exprint As exontrol.EXPRINTLib.exprint = New exontrol.EXPRINTLib.exprint()

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
	With exprint
		.PrintExt = Exg2antt1
		.Preview()
	End With
End Sub

or if you need to print multiple objects:

Private exprint As exontrol.EXPRINTLib.exprint = New exontrol.EXPRINTLib.exprint()

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
	With exprint
		.PrintExts = New Object() {Exg2antt1, Exg2antt2}
		.Preview()
	End With
End Sub
In these samples, the exontrol's eXG2antt/WPF is being printed. Replace the exg2antt in the sample with the name of the control to be printed.
WPF.8:
Change the IsEnabled property of the component on False ( By default, it is True ). This way the application cursor will shown the cursor as defined by Mouse.OverideCursor property when it hovers the component. The IsEnabled property specifies whether the element/component is enabled or disabled. Disabled elements do not participate in hit testing or focus and therefore will not be sources of input events.

Sample:

Exg2antt1.IsEnabled = False
Mouse.OverrideCursor = Cursors.Wait
WPF.9:
The idea is that you can use the Loaded event just for initialization of the component that does not take longer time such as setting the chart, adding columns, and use the ContentRendered event to load the items/data. Also, you can update the Cursor property of the Window during loaded as in the following sample:

C#

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void Window_ContentRendered(object sender, EventArgs e)
    {
        exg2antt1.BeginUpdate();
        string[] v = new string[100000];
        exg2antt1.PutItems(v);
        exg2antt1.EndUpdate();
        Cursor = Cursors.Arrow;
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        exg2antt1.BeginUpdate();
        exg2antt1.Columns.Add("Task");
        exg2antt1.Chart.FirstVisibleDate = new DateTime(2008, 1, 1);
        exg2antt1.Chart.PaneWidthLeft = 148;
        exg2antt1.Chart.LevelCount = 2;
        exg2antt1.EndUpdate();
        Cursor = Cursors.Wait;
    }

    private void exg2antt1_AddItem(object sender, int Item)
    {
        DateTime dt = exg2antt1.Chart.FirstVisibleDate;
        dt = dt.AddDays(exg2antt1.Items.get_ItemToIndex(Item) + 1);
        exg2antt1.Items.AddBar(Item, "Task", dt, dt.AddDays(4));
    }
}

VB/NET

Imports wpf
Imports System.Drawing

Class Window1
    Private Sub Window1_ContentRendered(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ContentRendered
        With Exg2antt1
            .BeginUpdate()
            Dim v(100000) As String
            .PutItems(v)
            .EndUpdate()
        End With
        Cursor = Cursors.Arrow
    End Sub

    Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        With Exg2antt1
            .BeginUpdate()
            .Columns.Add("Task")
            With .Chart
                .FirstVisibleDate = New DateTime(2008, 1, 1)
                .PaneWidthLeft = 148
                .LevelCount = 2
            End With
            .EndUpdate()
        End With
        Cursor = Cursors.Wait
    End Sub

    Private Sub Exg2antt1_AddItem(ByVal sender As Object, ByVal Item As Integer) Handles Exg2antt1.AddItem
        With Exg2antt1.Items
            Dim dt As DateTime = Exg2antt1.Chart.FirstVisibleDate
            dt = dt.AddDays(.get_ItemToIndex(Item) + 1)
            .AddBar(Item, "Task", dt, dt.AddDays(4))
        End With
    End Sub
End Class
The sample uses the exontrol's eXG2antt/WPF component. The Loaded event sets the chart's options and loads a column. The ContentRendered event loads 100.000 items using the PutItems. The AddItem event is fired for each new item being added during the PutItems, where a new bar is added AddBar method of the Items objects.
WPF.10:

Drag-and-drop is one of the fundamental metaphors underlying the Microsoft� Windows� family of operating systems. Users understand that some items can be moved around by holding the mouse down on them, and that they'll get appropriate visual feedback when they're over a spot where the item can be dropped. They expect to be able to move data and images from one spot to another this way. Visual Basic .NET makes it easy to implement drag-and-drop in your own applications. You can control all aspects of the process, including which controls allow dragging, what data they make available to drag, and where it can be dropped. You can implement this both within a single application and between applications.

Drag-and-drop operations typically involve two parties: a drag source from which the dragged object originates and a drop target which receives the dropped object. The drag source and drop target may be UI elements in the same application or a different application.

Beginning a Drag-and-Drop Operation

The drag source (the control in this case) initiates a drag-and-drop operation by calling the static DragDrop.DoDragDrop method and passing the transferred data to it. The DoDragDrop method will automatically wrap the data in a DataObject if necessary. For greater control over the data format, you can wrap the data in a DataObject before passing it to the DoDragDrop method. The drop target is responsible for extracting the data from the DataObject. It is the responsibility of your application to determine when a drag occurs, and then initiate the drag-and-drop operation. Typically, this is when a MouseDownEvent and MouseMoveEvent sequence of events occurs over the control to be dragged.

Accepting Data From a Drag Operation

Any control can accept data from a drag-and-drop operation in progress. To designate a control as a drop zone, you must do three things:

  1. Set the AllowDrop property of the control to True. Gets or sets a value indicating whether this element can be used as the target of a drag-and-drop operation.
  2. Handle the Drop event of the control. This event occurs when an object is dropped on the drop target.

The following VB.NET sample shows how you add Drag and Drop support for the eXG2antt/WPF component.

  1. Go to XAML file, and add AllowDrop ="True" MouseMoveEvent="Exg2antt1_MouseMoveEvent" Drop="Exg2antt1_Drop"
  2. Complete the MouseMoveEvent and Drop handlers as follows

Private Sub Exg2antt1_MouseMoveEvent(ByVal sender As System.Object, ByVal Button As System.Int16, ByVal Shift As System.Int16, ByVal X As System.Int32, ByVal Y As System.Int32)
    If (Button = 1) Then
        DragDrop.DoDragDrop(Me, "just a text being dragged", DragDropEffects.Copy)
    End If
End Sub

Private Sub Exg2antt1_Drop(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
    MessageBox.Show(e.Data.GetData(DataFormats.StringFormat))
End Sub
Run the sample, click and drag an item to a new position. The "just a text being dragged" message box will be displayed as soon as you drop the data inside the control.