Locations of visitors to this page
Onteora Software - December 2006

Onteora Software

Ken Tucker's Blog

About the author

Author Name is someone.
E-mail me Send mail

Recent posts

Recent comments

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

Data From Multiple Tables in a DataGridView

Data From Multiple Tables in a DataGridView



There is Msdn Knowledge base article which shows how to create a JoinView class. The JoinView class is for joining 2 tables together for data binding. Basically you load 2 or more tables into a dataset and set up some data relations for the related tables. When you create the Joinview the first argument is the main table, 2nd is a list of fields you want to show, 3rd is a filter, and 4th is the field to sort on. The last 2 arguments are option. Since the article includes a vb sample I am posting a c# example. I would recommend compiling JoinView.VB into a class so you use it with c#. I named my dll MSDNClasses.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using MSDNClasses;

namespace CSDGVMultiTable
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        DataSet ds = new DataSet();
        JoinView jv;

        private void Form1_Load(object sender, EventArgs e)
        {
            SqlConnection conn = new SqlConnection(@"server=.\sqlexpress;integrated security=true;database=northwind");
            SqlDataAdapter daCust = new SqlDataAdapter(@"Select * From Customers", conn);
            SqlDataAdapter daEmp = new SqlDataAdapter(@"Select * From Employees", conn);
            SqlDataAdapter daOrd = new SqlDataAdapter(@"Select * From Orders", conn);

            daCust.Fill(ds, "Cust");
            daEmp.Fill(ds, "Emp");
            daOrd.Fill(ds, "Ord");

            // Create some data relations for the joinview to use

            ds.Relations.Add("CustOrd", ds.Tables["Cust"].Columns["CustomerID"], ds.Tables["Ord"].Columns["CustomerID"]);
            ds.Relations.Add("EmpOrd", ds.Tables["Emp"].Columns["EmployeeID"], ds.Tables["Ord"].Columns["EmployeeID"]);

            // Create Join View
            // Select fields for JoinView,  a filter to use, and Column to sort on

            jv = new JoinView(ds.Tables["Ord"],
                "OrderID,CustomerID,EmployeeID,OrderDate,CustOrd.CompanyName Company,CustOrd.ContactName Contact,CustOrd.ContactTitle Position,EmpOrd.FirstName,EmpOrd.LastName",
                "", "");

            dataGridView1.DataSource = jv;

        }
    }
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: DataGridView | C#
Posted by Ken Tucker on Saturday, December 30, 2006 11:12 PM
Permalink | Comments (0) | Post RSSRSS comment feed

WPF: DataBind a ListView

WPF: DataBind a ListView



There is not a DataGrid or DataGridView in Windows Presentation Foundation.  Use the ListView to display data in a table.  In the window's Xaml define the listview and the fields you want displayed.  The code behind file is where you get the data from the Northwind database and bind the listview.



The Windows Xaml


<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WPF1" Height="300" Width="300"
    >
  <Grid>
    <ListView Margin="25,22,30,48" Name="ListView1" >
      <ListView.View>
        <GridView >
          <GridViewColumn Header ="Last Name" DisplayMemberBinding="{Binding LastName}" Width="100"></GridViewColumn>
          <GridViewColumn Header ="First Name" DisplayMemberBinding="{Binding FirstName}" Width="100"></GridViewColumn>
        </GridView>
      </ListView.View>
    </ListView>
  </Grid>
</Window>


The Code Behind


Imports System.Data

' Interaction logic for Window1.xaml
Partial Public Class Window1
    Inherits System.Windows.Window

    Public Sub New()
        InitializeComponent()
        Dim dt As New DataTable

        Dim strConn As String = _
           "Server = .\sqlexpress;Database = NorthWind; Integrated Security = SSPI;"
        Dim conn As New SqlConnection(strConn)
        Dim da As New SqlDataAdapter("Select LastName, FirstName from Employees", conn)
        da.Fill(dt)
        ListView1.DataContext = dt
        Dim bind As New Binding
        ListView1.SetBinding(ListView.ItemsSourceProperty, bind)
    End Sub

End Class

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: WPF
Posted by Ken Tucker on Saturday, December 23, 2006 11:12 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Printer Compatibility Library 1.0

Printer Compatibility Library 1.0



Visual Basic 6.0 and earlier had a printer object which made it simple to print. The Printer Compatibility Library 1.0 makes it possible to use the same object with VB or C# 2005. After installing the Power Pack just add a reference to Microsoft.VisualBasic.PowerPacks.Printing.Printer

 

VB Sample

Imports Microsoft.VisualBasic.PowerPacks.Printing.Compatibility.VB6

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim p As New Printer
        p.Print("Page 1")
        p.NewPage()
        p.Print("Page 2")
        p.EndDoc()
    End Sub
End Class

 

C# Sample

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualBasic.PowerPacks.Printing.Compatibility.VB6;

namespace PrinterCS
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Printer p = new Printer();
            p.Print("Page 1");
            p.NewPage();
            p.Print("Page 2");
            p.EndDoc();
        }
    }
}
 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General | VB | C#
Posted by Ken Tucker on Friday, December 22, 2006 11:12 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Datagrid Validation

Datagrid Validation


The DataGridView has a CellValidating Event to validate the data entered. Here is how to do it with the DataGrid.


There are 2 method to do this. My method is to add a tablestyle to the datagrid. For the cells I want to validate I handle the DataGridTextBoxColumn's Textbox's Validate event. George Shepherd's method is use the CurrentCellChanged event. You can read about this method in the Windows Forms FAQ.



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace CSDatagrid
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            String strConn = "Server = .\\SqlExpress;Database = Pubs;Integrated Security = SSPI;";
            DataTable dt = new DataTable();
            SqlConnection conn = new SqlConnection(strConn);
            SqlDataAdapter da = new SqlDataAdapter("Select Title, price from titles", conn);
            da.Fill(dt);
            dataGrid1.DataSource = dt;
            CurrencyManager cm = this.BindingContext[dt] as CurrencyManager;
            PropertyDescriptor pd = cm.GetItemProperties()["price"];

            DataGridTableStyle ts = new DataGridTableStyle();
            ts.MappingName = dt.TableName;

            DataGridTextBoxColumn tcTitle = new DataGridTextBoxColumn();
            tcTitle.MappingName = "Title";
            tcTitle.HeaderText = "Title";
            tcTitle.Width = 250;
            DataGridTextBoxColumn tcPrice = new DataGridTextBoxColumn(pd, "c2");
            tcPrice.MappingName = "price";
            tcPrice.HeaderText = "Book Price";
            tcPrice.Width = 100;
            tcPrice.TextBox.Validating += new CancelEventHandler(TextBox_Validating);
            ts.GridColumnStyles.Add(tcTitle);
            ts.GridColumnStyles.Add(tcPrice);

            dataGrid1.TableStyles.Add(ts);
        }

        void TextBox_Validating(Object sender, CancelEventArgs e)
        {
            TextBox txt = (TextBox)sender;
            txt.Text = txt.Text.Replace("$", "");
        }

    }
}

You will find a VB example on the VB-Tips Website

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: DataGrid | C#
Posted by Ken Tucker on Tuesday, December 19, 2006 11:12 PM
Permalink | Comments (0) | Post RSSRSS comment feed

UpdatePanel Gotcha

UpdatePanel Gotcha


Do not update the contents inside a UpdatePanel with java script. You will not get the resuts you expect.


For example place a span and button inside an update panel.When you click on a button control the java script onClientClick will fire followed by the Click event for the button. So if we update the span's text with onClientClick the text will update briefly then the UpdatePanel will catch the post back made by the click event and erase our changes.



<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>

<%@ Register Assembly="Microsoft.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace="Microsoft.Web.UI" TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>

    <script type="text/javascript">
        function displayClick()
        {
            $get("span1").innerHTML="Hello World";
        }
    </script>

</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">
            </asp:ScriptManager>
             <asp:UpdatePanel ID="UpdatePanel1" runat="server" >
                <ContentTemplate>
                   <span id="span1"></span>
                    <br />
                    <asp:linkButton runat="server" Text="Button" ID="button1" OnClientClick="displayClick();" />
                </ContentTemplate>
            </asp:UpdatePanel>
        </div>
    </form>
</body>
</html>

By moving the Span outside the update panel we will still be able to update the contents of the span without posting back. The UpdatePanel still prevents the pages postback.



<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>

<%@ Register Assembly="Microsoft.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace="Microsoft.Web.UI" TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>

    <script type="text/javascript">
        function displayClick()
        {
            $get("span1").innerHTML="Hello World";
        }
    </script>

</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">
            </asp:ScriptManager>
            <span id="span1"></span>
            <br />
            <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                <ContentTemplate>
                    <asp:LinkButton runat="server" Text="Button" ID="button1" OnClientClick="displayClick();" />
                </ContentTemplate>
            </asp:UpdatePanel>
        </div>
    </form>
</body>
</html>

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Ajax
Posted by Ken Tucker on Wednesday, December 13, 2006 11:12 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Vista Application Recovery

Vista Application Recovery


Ever want to add the ability to recover the user data if your application has crashed. Windows Vista has some nice apis to make this easy.


The RegisterApplicationRestart api tells Vista we would like the app to restart if it crashes or hangs. This api takes two arguments a string which will be the command line argument when the application restarts and RestartFlags. For this example we will tell the app to always restart. Note the app must run 60 seconds before it will restart.



    Enum RestartFlags
        Always = 0
        Cyclical = 1
        NotifySolution = 2
        NotifyFault = 4
        DoNotRestartOnCrash = 8
        DoNotRestartOnHang = 16
        DoNotRestartOnUpdate = 32
    End Enum

    Declare Auto Function RegisterApplicationRestart Lib "kernel32.dll" (ByVal strMessage As String, ByVal RestartOption As RestartFlags) As Integer

RegisterApplicationRestart("Restarted", RestartFlags.Always)



 

The RegisterApplicationRecoveryCallback will allow us to register a function to run if our application crashes or hangs. This will allow us to save the users work before the app terminates. Note that you will not have access to the forms controls but you will have access to the variables. If you want to be able to recover the text in a textbox I would use a variable which is updated in the textboxes textchanged event. Inside the callback function you must tell Vista you are working with the ApplicationRecoveryInProgress function. When the recovery is complete tell Vista with the ApplicationRecoveryFinished function.



    Declare Auto Function RegisterApplicationRecoveryCallback Lib "kernel32.dll" (ByVal cb As App_Recovery_Callback, ByVal Param As String, ByVal PintInterval As Integer, ByVal flags As RestartFlags) As Integer
    Declare Auto Function ApplicationRecoveryInProgress Lib "kernel32.dll" (ByRef Canceled As Boolean) As Integer
    Declare Auto Function ApplicationRecoveryFinished Lib "kernel32.dll" (ByRef Success As Boolean) As Integer

    Delegate Function App_Recovery_Callback(ByVal Param As String) As Integer


    Private Function Recover(ByVal Param As String) As Integer
        Dim b As Boolean
        Using sw As New StreamWriter("Recovered.txt", False)
            ApplicationRecoveryInProgress(b)
            sw.WriteLine(strTextbox)
            ApplicationRecoveryInProgress(b)
            sw.Flush()
            sw.Close()
        End Using
        ApplicationRecoveryFinished(True)

        Return 0
    End Function

One last thing. The .Net framework will catch the error and prevent our recovery callback function from being called. So we need to uncheck the enable application framework box in my projects so we can make the application start with Sub Main. In Sub Main we can Set the UnHandledException Mode to throw exception so Vista will know about the crash


    Public Shared Sub Main()
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)
        Application.Run(New Form1)
    End Sub


For the sample Application I have a form with a label (label1), textbox (textbox1), 2 buttons (btnCrash an btnHang), and a timer. The timer is used to update the label with how long the app ran. The 2 buttons will hang or crash the app. Here is the code for the sample app. For the app recovery to work run the program without debugging (ctrl+F5).



Imports System.IO

Public Class Form1
    Enum RestartFlags
        Always = 0
        Cyclical = 1
        NotifySolution = 2
        NotifyFault = 4
        DoNotRestartOnCrash = 8
        DoNotRestartOnHang = 16
        DoNotRestartOnUpdate = 32
    End Enum

    Dim strTextbox As String

    Declare Auto Function RegisterApplicationRestart Lib "kernel32.dll" (ByVal strMessage As String, ByVal RestartOption As RestartFlags) As Integer
    Declare Auto Function RegisterApplicationRecoveryCallback Lib "kernel32.dll" (ByVal cb As App_Recovery_Callback, ByVal Param As String, ByVal PintInterval As Integer, ByVal flags As RestartFlags) As Integer
    Declare Auto Function ApplicationRecoveryInProgress Lib "kernel32.dll" (ByRef Canceled As Boolean) As Integer
    Declare Auto Function ApplicationRecoveryFinished Lib "kernel32.dll" (ByRef Success As Boolean) As Integer

    Delegate Function App_Recovery_Callback(ByVal Param As String) As Integer

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Static x As Integer = 0
        Label1.Text = String.Format("App running {0} seconds", x)
        x += 1
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If My.Application.CommandLineArgs.Count > 0 Then
            TextBox1.Text = My.Computer.FileSystem.ReadAllText("Recovered.txt")
            ApplicationRecoveryFinished(True)
        End If

        'register app to restart
        RegisterApplicationRestart("Restarted", RestartFlags.Always)

        'setup the Recovery Callback
        RegisterApplicationRecoveryCallback(AddressOf Recover, "Recover Data", 50000, RestartFlags.Always)
        'start a timer to show how long the app has run
        Timer1.Interval = 1000
        Timer1.Enabled = True

    End Sub

    Private Function Recover(ByVal Param As String) As Integer
        Dim b As Boolean
        Using sw As New StreamWriter("Recovered.txt", False)
            ApplicationRecoveryInProgress(b)
            sw.WriteLine(strTextbox)
            ApplicationRecoveryInProgress(b)
            sw.Flush()
            sw.Close()
        End Using
        ApplicationRecoveryFinished(True)

        Return 0
    End Function

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCrash.Click
        Throw New Exception("Crash Me!!!")
    End Sub

    Public Shared Sub Main()
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)
        Application.Run(New Form1)
    End Sub

    Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
        strTextbox = TextBox1.Text
    End Sub

 

    Private Sub btnHang_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHang.Click
        Do While True
            ' lock me up
        Loop
    End Sub
End Class

 

Daniel Moth and Bart De Smet's have some nice blog entries about using app recovery with c# console apps. You can register your application (a digital signature is required) at the Windows Quality Online Services site to be able to see any error reports sent by your app.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: VB | Vista
Posted by Ken Tucker on Friday, December 08, 2006 11:12 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Vista Task Dialog

Vista Task Dialog


Windows Vista has some cool looking new Dialog's. This example will show how to use the TaskDialog an improved message box with Visual Studio 2005.

 


Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim x As Integer
        TaskDialogHelper.TaskDialog(Me.Handle, IntPtr.Zero, "Title", "Are you sure?", "This is a test", TaskDialogHelper.TaskDialogButtons.Ok, TaskDialogHelper.TaskDialogIcon.Question, x)
    End Sub
End Class

Public Class TaskDialogHelper
    Public Enum TaskDialogButtons
        Ok = &H1
        Cancel = &H8
        Yes = &H2
        No = &H4
        Retry = &H10
        Close = &H20
    End Enum

    Public Enum TaskDialogIcon
        Information = UInt16.MaxValue - 2
        Warning = UInt16.MaxValue
        [Stop] = UInt16.MaxValue - 1
        Question = 0
        SecurityWarning = UInt16.MaxValue - 5
        SecurityError = UInt16.MaxValue - 6
        SecuritySuccess = UInt16.MaxValue - 7
        SecurityShield = UInt16.MaxValue - 3
        SecurityShieldBlue = UInt16.MaxValue - 4
        SecurityShieldGray = UInt16.MaxValue - 8
    End Enum

    Public Enum TaskDialogResult
        None
        OK
        Cancel
        Yes = 6
        No = 7
        Retry = 4
        Close = 8
    End Enum

    Public Declare Auto Function TaskDialog Lib "comctl32.dll" (ByVal hWnd As IntPtr, ByVal hInstance As IntPtr, _
        ByVal WindowTitle As String, ByVal MainInstruction As String, ByVal Content As String, _
        ByVal CommonButton As Integer, ByVal DialogIcon As Integer, ByRef PushedButton As Integer) As Integer

End Class

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Vista
Posted by Ken Tucker on Thursday, December 07, 2006 4:12 AM
Permalink | Comments (0) | Post RSSRSS comment feed