Justin Finch's Blog
My Links
Blog Stats
  • Posts - 7
  • Stories - 0
  • Comments - 0
  • Trackbacks - 1
Archives

Wednesday, June 06, 2007

If you have been working with WPF and have had issues with your ComboBox or any list control binding then you can stop pulling your hair out.  The problem occurs when you try to bind the SelectedValue property of the control to a Nullable Int (int?).  I am currently working with Microsoft to resolve the root problem, but here is a work around for now:

1.  Create an IValueConveter:

public class NullIntToNegOneConverter : IValueConverter

    {

 

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            if (value == null)

            {

                return -1;

            }

            else

            {

                return value;

            }

        }

 

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            int i;

            if (int.TryParse(value.ToString(), out i))

            {

                if (i == -1)

                {

                    return null;

                }

                else

                {

                    return value;

                }

            }

            else

            {

                return value;

            }

        }

 

    }

 

2. Add a -1 value to the list that your control is bound to:

Person nullPerson = new Person();

      nullPerson.Id = -1;

      nullPerson.Name = "None";

      people.Insert(0, nullPerson);

 

3. Bind to the Selected Value using the Converter:

<ComboBox ItemsSource="{Binding Source={x:Static Application.Current},Path=People}"

SelectedValuePath="Id" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="False"

Margin="3,3,3,3" HorizontalAlignment="Right" FontSize="18"

SelectedValue="{Binding Path=PersonId, UpdateSourceTrigger=Explicit, Converter={StaticResource NullIntToNegOneConverter}}"/>

 

You should be all set.  If your id is null then you get the -1 value that you inserted in the list because the convert converts the null value to -1.  However, when you go to save it to the database, the convert also converts the -1 back to a null value, so you won’t have any -1 values in your database.

posted @ 11:12 AM | Feedback (0)

Tuesday, May 29, 2007

I ran across a weird error when I was trying to open an existing SSIS package in VS2005:

Error      1  Error loading 'Package.dtsx' : Unable to cast COM object of type 'Microsoft.SqlServer.Dts.Runtime.Wrapper.PackageNeutralClass' to interface type 'Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSContainer90'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{8BDFE892-E9D8-4D23-9739-DA807BCDC2AC}' failed due to the following error: Library not registered. (Exception from HRESULT: 0x8002801D (TYPE_E_LIBNOTREGISTERED))

 

To fix the problem do the following:

1.       Open the command prompt

2.       Navigate to C:\Program Files\Microsoft SQL Server\90\DTS\Binn

3.       Run C:\Program Files\Microsoft SQL Server\90\DTS\Binn>regsvr32 dts.dll

That should fix the problem.

posted @ 9:00 AM | Feedback (0)

Monday, March 19, 2007

I have recently been working on a WPF touch screen application that doesn’t lend it self well to normal scroll bars.  Luckly this is no problem with WPF because you have the ability to easily modify how a control is rendered.  Below is a rough template that puts a button above and below scrollable content and when clicked they provide the same functionality as the default scroll bar.

 

<ControlTemplate TargetType="{x:Type ScrollViewer}"   
 
x:Key="ButtonOnlyScrollViewer">

<Grid>

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

<RowDefinition Height="Auto"/>

Grid.RowDefinitions>

<Grid.ColumnDefinitions>

<ColumnDefinition />

<ColumnDefinition />

Grid.ColumnDefinitions>

<RepeatButton Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch"
 
Content="ScrollUp"Command="ScrollBar.LineUpCommand"/>

<ScrollContentPresenter Grid.Row="1" Content="{TemplateBinding Content}"  
 
Grid.Column="0" ScrollViewer.VerticalScrollBarVisibility ="Auto"  
 
Height="Auto" Margin="{TemplateBinding Margin}"/>

<RepeatButton Grid.Row="2" Grid.Column="0" Height="20"
 
Content="ScrollDown"

  Command="ScrollBar.LineDownCommand"/>

Grid>

ControlTemplate>

posted @ 4:00 PM | Feedback (0)

Thursday, January 25, 2007

With all the new development tools coming out it is difficult to figure out which version works with which version.  Some are in Beta, some in CTP and others fully released.  If you are looking to start developing in WPF and WCF here are the 3 things you need:

 

1. .NET 3.0 Framework - Version 3.0

http://www.microsoft.com/downloads/details.aspx?FamilyId=10CC340B-F857-4A14-83F5-25634C3BF043&displaylang=en

 

2. Windows SDK - Version 1.0

http://www.microsoft.com/downloads/details.aspx?FamilyId=C2B1E300-F358-4523-B479-F53D234CDCCF&displaylang=en

 

3. VS 2005 Extensions - November 2006 CTP

http://www.microsoft.com/downloads/details.aspx?FamilyId=F54F5537-CC86-4BF5-AE44-F5A1E805680D&displaylang=en

 

Assuming that you have Visual Studio 2005 installed, download and install them in the above order and you should be ready to go.

posted @ 8:31 AM | Feedback (0)

Friday, July 28, 2006

Email me at justin.finch@parivedasolutions.com for a copy of the dll that contains the control used in the example.

 

Google recenlty introduce Google Checkout.  “Google Checkout is a checkout process that you integrate with your website, enabling your customers to buy from you quickly and securely, using a single username and password. Once they do, you can use Google Checkout to charge their credit cards, process their orders, and receive payment in your bank account.”

 

They currently have no ASP.NET examples posted on their site so I have created an ASP.NET 2.0 Custom Web Control that will allow you to easily integrated with their service by simply dropping a control on a page and specifying a few parameters.  So here it is…

 

Step 1: Modify the Web.Config file

Add the following entry to the web.config file.  This will allow you to use the control on any page with out having to add the control directive to each page.  Also, don’t for get to add the dll to the bin directory of your website.

 

<system.web>

    <pages maintainScrollPositionOnPostBack="true">

      <controls>

        <add tagPrefix="Google" namespace="Google.Web.UI.WebControls"

 assembly="Google.Web"/>

       controls>

   pages>

 

Step 2: Add the control to the page.

This is pretty simple, but just make sure you add it outside to the form tags on the page.  Specify your MerchantId and MerchantKey that you received for Google and tell the control if it should use the sandbox (test) or the production service.  You will need to register for both through Google.

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

    <title>Untitled Pagetitle>

head>

<body>

    <form id="form1" runat="server">

    <div>

       Place info here...

    div>

    form>

    <Google:CheckoutButton MerchantId="101156456465"    
            MerchantKey="234lk4j53452lkj34" UseSandBox="true"
            runat="server" ID="btnGoogleCheckout"/>

body>

html>

 

Step 3: Set the Shopping Cart XML Property

In the code behind for the page set the ShoppingCartXml property.  For testing purpose I simply Desearlized Google's sample xml into a ShoppingCart object.  The sample xml can be found on their site and here is a great article on how to create a C# object base on the XSD schema file provided by Google. http://www.netomatix.com/Products/Ecomm/GoogleCheckOut.aspx

 

protected void Page_Load(object sender, EventArgs e)

    {

        btnGoogleCheckout.CartXml = GetCartXML();

    }

 

private string GetCartXML()

    {

        string xmlFile = "checkout-shopping-cart-SIMPLE.xml";

 

        XmlDocument xml = new XmlDocument();

        xml.Load(Server.MapPath(xmlFile));

 

        return xml.InnerXml;

    }

 

 

You are all set.  Just click the button and you will see the shopping cart appear on the Google site.  Let me know if you have any questions or problems with the control.

 

           

For more information visit the following link to the developers guide.

 

            http://code.google.com/apis/checkout/developer/index.html

 

 

posted @ 6:46 PM | Feedback (0)

Tuesday, December 13, 2005

As many of you know, using MSDABB (Microsoft Data Access Application Block) can greatly simplify your data access code, but I wanted to bring to your attention a new helper class that is aimed toward taking advantage of the new ADO.NET 2.0.  Its primary goal is to create a provider independent data access  by using new Factory classes of ADO.NET 2.0.

 

I have just begun to play with this new helper class and have posted a few questions to the developer, but I thought I would bring it to everyone’s attention and give some links for more information.

 

A detailed article on the Helper Class can be found here:

http://www.dotnetbips.com/articles/displayarticle.aspx?id=479

 

 

The new Helper Class, along with samples, can be downloaded here:

http://www.binaryintellect.com/products/Default.aspx

 

Feel free to post replies to let me know what you think.

posted @ 10:31 AM | Feedback (1)

Tuesday, November 22, 2005

If you have ever had to display large a dataset on the web, you will soon realize they can bring your application to a halt.  A solution to this problem is paging.  Paging allows smaller results set to be returned and displayed on the client, which greatly improves performance. 

 

Introduction

For this example I will user Pariveda’s custom Pagable/Sortable repeater control which will soon be included in the Pariveda.Web dll.  I will demonstrate how to:

 

  1. Create a Stored Procedure that allows for Paging and Sorting
  2. Write a Business Controller to call the stored procedure
  3. Add the custom control to a web page
  4. Write code to hook into the controls events in order to call the Stored Procedure and return the proper result set

 

Create the Stored Procedure

I used the infamous Northwind database for this example.  I will select Customer records based on the current page and sort information from the control.

 

First, you must declare parameters that will be needed for paging:

 

            CREATE  PROCEDURE dbo.Northwind_CustomersGetPaged

                                                     @startRow int

                                                   , @endRow int

                                                   , @sortColumn varchar(100)

                                                   , @sortDirection char

 

Next, either a Table Variable or Temp Table is needed to hold you queried results.  In this example I have chosen to use a Table Variable.  If you use a temp table make sure to drop it at the end of the procedure.  The Row ID will be used to determine which rows (Page) of data to return.  This is based on the information passed in from the control that I will discuss later.

 

            DECLARE @results TABLE

            (

                         rowId              int identity

                        ,CustomerID    nchar(5)

                        ,CompanyName           nvarchar(40)

                        ,Address          nvarchar(60)

                        ,City                 nvarchar(15)

                        ,Phone              nvarchar(24)

            )

 

After we have declared the results table we must populate it with data based on the sort criteria received from the control.  Notice the order by is a case statement.  This is done in order to transform the @sortColumn and @sortDirection into a SQL order by statement.

 

            INSERT INTO @results

            (

                         CustomerID   

                        ,CompanyName          

                        ,Address         

                        ,City                

                        ,Phone

            )

            SELECT  

                         CustomerID   

                        ,CompanyName          

                        ,Address         

                        ,City                

                        ,Phone             

            FROM

                        dbo.Customers

            ORDER BY

                        CASE 

WHEN @sortColumn = 'Customer ID' and @sortDirection = 'D' then CustomerID

 

WHEN @sortColumn ='Company Name' and @sortDirection = 'D' then CompanyName

 

WHEN @sortColumn ='Address' and @sortDirection = 'D' then Address

 

                                    WHEN @sortColumn ='City' and @sortDirection = 'D' then City

 

WHEN @sortColumn ='Phone' and @sortDirection = 'D' then Phone

                        END DESC,

                        CASE 

WHEN @sortColumn = 'Customer ID' and @sortDirection = 'A' then CustomerID

 

WHEN @sortColumn ='Company Name' and @sortDirection = 'A' then CompanyName

 

WHEN @sortColumn ='Address' and @sortDirection = 'A' then Address

 

                                    WHEN @sortColumn ='City' and @sortDirection = 'A' then City

 

WHEN @sortColumn ='Phone' and @sortDirection = 'A' then Phone

                        END ASC,

                        CompanyName

 

Finally, 2 results sets will need to be returned; one with a total count (“Virtual Count”) of all records that meet our criteria, and another with only the rows for the current page of the control.

 

            SELECT count(1) AS NumRows FROM @results

 

            SELECT * FROM @results

                        WHERE           rowID >= @startRow

                        AND    rowID <= @endRow

 

 

Writing the Business Controller

Calling the procedure is pretty straight forward.  For the example the stored procedure only accepts the Paging parameters, but you could add any additional parameters for your particular application.  One quick note, I used Microsoft’s Application Blocks to access the database.  The first results set returns the total number of customers and the next results set contains the specific customer data for the given page.  Both result sets are read into a Customer Object which is returned to the UI where it will be bound to the paging control.

 

using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using Microsoft.ApplicationBlocks.Data;
using PagedRepeaterExample.DataObject.Customer;
 
namespace PagedRepeater.Business
{
    /// <summary>
    /// Summary description for CustomerController.
    /// </summary>
    public class CustomerController
    {
private static readonly string CONNECTION_STRING = 
ConfigurationSettings.AppSettings.Get("ConnectionString");
        public CustomerController()
        {
        }
         public static Customers GetCustomers(int startRow,
                                             
int
endRow,
                                             
string
sortColumn,
                                             
string sortDirection)
        {
                   Customers customers = new Customers();
            CustomerCollection customerColleciton = new CustomerCollection();    
            SqlParameter[] parameters = new SqlParameter[]
            {
                new SqlParameter("@startRow", startRow),
                new SqlParameter("@endRow", endRow),
                new SqlParameter("@sortColumn", sortColumn),
                new SqlParameter("@sortDirection", sortDirection) 
            };
 
            try
            {
using(SqlDataReader reader =
 SqlHelper.ExecuteReader(CONNECTION_STRING,CommandType.StoredProcedure,
 "NorthWind_CustomersGetPaged",parameters))
                {
                    while(reader.Read())
                    {
                        customers.VirtualCount = (int)reader["NumRows"];
                    }
 
                    if(reader.NextResult())
                    {
                        while(reader.Read())
                        {
                            Customer customer = new Customer();
                            customer.CustomerId = reader["CustomerId"].ToString();
                            customer.CompanyName = reader["CompanyName"].ToString();
                            customer.City = reader["City"].ToString();
                            customer.Address = reader["Address"].ToString();
                            customer.Phone = reader["Phone"].ToString();
                            customerColleciton.Add(customer);
                        }
                    }
                }
            }
            catch(Exception ex)
            {
                return null;
            }
            customers.CustomerCollection = customerColleciton;
            return customers;
        }
    }
}

 

Add the Control

Adding the control to the page is similar to adding a regular repeater control.  The first thing is to add a page directive for the Pariveda.Web dll.

 

<%Register TagPrefix="pvs" Assembly="Pariveda.Web" namespace="Pariveda.Web.UI.WebControls"%>

 

The next step is to add the custom control to the page.  The “IsSortable” property of the repeater should be set to True and the “PageControllerContainerId” should be set to the id of the Place holder located in the header template.  The Place holder is used to hold the paging controls and can be place in either the Header Template of the Footer Template.  The SortLinkButton’s are used, of course, for sorting.  The only thing to watch with these is to make sure that the SortType property matches the Order By clause in the stored procedure.

           

     <form id="Form1" method="post" runat="server">

                <table width="100%">

                     <pvs:PagedRepeater id="rptCustomers" Runat="server"
                                                                                             IsSortable="true"
                                                                                              PagerControllerContainerId="CustomerPagerControls">

                                <HEADERTEMPLATE>

                                                <TR >

                                                                <TD colspan="5" align="right">

                                                                <asp:PlaceHolder id="CustomerPagerControls" Runat="server"></asp:PlaceHolder>

                                                                </TD>

                                                </TR>

                                                <TR bgcolor="Gainsboro">

                                                                <TD >

                                                                                <pvs:SortLinkButton ID="Sortablelinkbutton1"

                                                                                Runat="server"

                                                                                SortType="Customer ID"

                                                                                AscImage="images/ArrowAsc.gif"

                                                                                DecImage="images/ArrowDec.gif">Customer ID</pvs:SortLinkButton>

                                                                </TD>

                                                                <TD>

                                                                                <pvs:SortLinkButton ID="Sortablelinkbutton2"

                                                                                Runat="server"

                                                                                SortType="Company Name"

                                                                                AscImage="images/ArrowAsc.gif"

                                                                                DecImage="images/ArrowDec.gif">Company Name</pvs:SortLinkButton>

                                                                </TD>

                                                                <TD>

                                                                                <pvs:SortLinkButton ID="Sortlinkbutton1"

                                                                                 Runat="server"

                                                                                SortType="Address"

                                                                                AscImage="images/ArrowAsc.gif"

                                                                                 DecImage="images/ArrowDec.gif">Address</pvs:SortLinkButton>

                                                                </TD>

                                                                <TD>
                                                                            <pvs:SortLinkButton ID="Sortlinkbutton2"

                                                                                Runat="server"

                                                                                SortType="City"

                                                                                AscImage="images/ArrowAsc.gif"

              &n