Silverlight 3 combobox selectedvalue

by Andrei Hetel 25. July 2011 05:22

I was very unpleasant surprised to find out that there is no selectedvalue property for a combobox in Silverlight 3. Most of the time you want to perform an action based on a combo box selection change. So, I come up with a simple solution which will be detailed below.

 

XAML code:

<ComboBox x:Name="MyColors">

 

We need two simple classes to bind the combobox:

 

Public Class CComboItem

     Private _ID As Int64
     Private _Description As String

     Public Sub New(ByVal pid As Int64, ByVal pDesc As String)
         _ID = pid
         _Description = pDesc
     End Sub

     Public Property ID() As Int64
         Get
             Return _ID
         End Get
         Set(ByVal value As Int64)
             _ID = value
         End Set
     End Property

     Public Property Description() As String
         Get
             Return _Description
         End Get
         Set(ByVal value As String)
             _Description = value
         End Set
     End Property

End Class

 

Second class, more exactly a collection:

 

Imports System.Collections.ObjectModel

Public Class CComboList
     Inherits ObservableCollection(Of CComboItem)

     Public Sub addItem(ByVal itm As CComboItem)
         Add(itm)
     End Sub
End Class

 

Load the combo as follows:

 

Dim colorList As New CComboList
colorList.Add(New CComboItem(1, "red"))
colorList.Add(New CComboItem(2, "yellow"))
colorList.Add(New CComboItem(3, "blue"))
MyColors.ItemsSource = colorList
MyColors.DisplayMemberPath = "Description"
MyColors.SelectedIndex = 0

 

Finally, because the post is already too long, get selected value from the combo box:

 

Private Sub MyColors_SelectionChanged(ByVal sender As Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles MyColors.SelectionChanged
     Dim id As Int64
     If MyColors.SelectedItem Is Nothing Then Exit Sub
     ' here is the selected value...
     id = DirectCast(MyColors.SelectedItem, CComboItem).ID
End Sub

 

Pretty simple, but at least is doing the trick.

 

Web services - returning custom objects

by Andrei Hetel 13. November 2008 14:12

This article is focused on web services, more exactly about the way you can return a custom object into your client application (in my case a windows mobile application). The easiest way is to use a simple example. On web service project let's create a simple class with only 2 properties CastleId, CastleName:

 

<Serializable()> _
Public Class CCastle

  Private _CastleId As Int64
  Private _CastleName As String

  Public Sub New()
  End Sub
  Public Sub New(ByVal newCastleId As Int64, ByVal newCastleName As String)
    _CastleId = newCastleId
    _CastleName = newCastleName
  End Sub

  Public Property CastleId() As Int64
    Get
      Return _CastleId
    End Get
    Set(ByVal value As Int64)
      _CastleId = value
    End Set
  End Property
  Public Property CastleName() As String
    Get
      Return _CastleName.Trim
    End Get
    Set(ByVal value As String)
      _CastleName = value
    End Set
  End Property

End Class

 

Please note that the class is marked as serializable and the properties are public read/write, to be able to use it into the client application created later.

Now, let's create a collection class, also serializable:

 

<Serializable()> _
Public Class CCastleList
  Private _CastleList As List(Of CCastle)

  Public Property CastleList() As List(Of CCastle)
    Get
      Return _CastleList
    End Get
    Set(ByVal value As List(Of CCastle))
      _CastleList = value
    End Set
  End Property
End Class

 

Finally, web method:

 

<WebMethod()> _
Public Function CastleList() As CCastleList

  Dim cl As New CCastleList
  Dim myList As New List(Of CCastle)

  myList.Add(New CCastle(1, "Castle1"))
  myList.Add(New CCastle(2, "Castle2"))
  cl.CastleList = myList
  Return cl

End Function

 

That's all on the web service side. Now, let's create a client application, reference the web service and call the web method. Like this:

 

Public Sub LoadCastleList()

  Dim ws As localhost.YsaMain
  Dim cl As localhost.CCastleList
  Dim castle As localhost.CCastle

  Try
    ws = New localhost.YsaMain
    cl = ws.CastleList()

    For Each castle In cl.CastleList
      debug.writeline (castle.CastleId & " " & castle.CastleName)
    Next castle

  Catch ex As Exception
  End Try
End Sub

 

Save repeater data to CSV

by Andrei Hetel 9. September 2008 10:36

I was working recently on a web project. One of the requirements was to save the data from a repeater control (I decide to use repeater and not DataGrid because of speed) into a CSV file. Don't know if this is the best method or not, but this is the way I did it. Relevant code in ASPX page:

<table>
<asp:Repeater ID="test" runat="server" >
  <HeaderTemplate>
    <tr>
      <td>Item</td>
      <td>Count</td>
      <td>Price</td>
      <td>VAT</td>
      <td>Total</td>
    </tr>
  </HeaderTemplate>
  <ItemTemplate>
    <tr>
      <td><asp:label ID="Item" Text=<%#DataBinder.Eval(Container, "DataItem.Item")%> runat="server" /></td>
      <td><asp:label ID="Cnt" Text=<%#DataBinder.Eval(Container, "DataItem.Cnt")%> runat="server" /></td>
      <td><asp:label ID="Price" Text=<%#DataBinder.Eval(Container, "DataItem.Price")%> runat="server" /></td>
      <td><asp:label ID="VAT" Text=<%#DataBinder.Eval(Container, "DataItem.VAT")%> runat="server" /></td>
      <td><asp:label ID="Total" Text=<%#DataBinder.Eval(Container, "DataItem.Total")%> runat="server" /></td>
    </tr>
  </ItemTemplate>
</asp:Repeater>
</table>
<asp:Button id="Export" Text="Export" runat="server" />

 

We need the following class:

 

Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.IO
Imports System.Text

Public Class CCSVExport
  Private _pPage As Page = Nothing
  Private _Title As String
  Private _ColumnList As ArrayList
  Private _FName As String

  Public Sub New(ByVal pPage As Page, ByVal tit As String, ByVal fName As String, ByVal colList As ArrayList)
    _pPage = pPage
    _Title = tit
    _FName = fName
    _ColumnList = colList
  End Sub

  Public Sub ExportRepeater(ByVal rpt As Repeater)
    Dim context As System.Web.HttpContext
    Dim byteArray() As Byte

    context = System.Web.HttpContext.Current
    context.Response.Clear()
    context.Response.Buffer = True
    context.Response.ContentType = "application/vnd.ms-excel"
    context.Response.Charset = ""
    _pPage.EnableViewState = False
    context.Response.AddHeader("Content-Disposition", "attachment;filename=" & _FName & ";")
    byteArray = System.Text.Encoding.ASCII.GetBytes(BuildData(rpt).ToString)
    context.Response.BinaryWrite(byteArray)
    context.Response.End()
  End Sub

  Private Function BuildData(ByVal rpt As Repeater) As StringBuilder

    Dim ri As RepeaterItem
    Dim currentLine As String
    Dim arrayIndex As Int16
    Dim sb As New StringBuilder

    sb.AppendLine(_Title)
    For Each ri In rpt.Items

      currentLine = ""
      If ri.ItemType = ListItemType.AlternatingItem Or ri.ItemType = ListItemType.Item Then
        For arrayIndex = 0 To _ColumnList.Count - 1
          currentLine &= CType(ri.FindControl(_ColumnList.Item(arrayIndex)), Label).Text.Trim & ","
        Next arrayIndex
        sb.AppendLine(currentLine)
      End If
    Next ri
    Return sb
  End Function
End Class

 

Code in page load, just binding the repeater to a datatable:

 

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

  test.DataSource = dt
  test.DataBind()

End Sub

 

Finally, export the data:

Protected Sub Export_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Export.Click

  Dim fileTitle As String
  Dim export As CCSVExport
  Dim arrFields As ArrayList

  fileTitle = "Test"
  arrFields = New ArrayList

  arrFields.Add("Item")
  arrFields.Add("Cnt")
  arrFields.Add("Price")
  arrFields.Add("VAT")
  arrFields.Add("Total")
  export = New CCSVExport(Page, fileTitle, "test.csv", arrFields)
  export.ExportRepeater(test)
End Sub

 

SQL Server 2005 CLR Integration

by Andrei Hetel 6. August 2008 10:25

There are a lot of articles on the net about how to achieve this, some of them good, some other hard to follow. My problem was pretty simple: scan a folder from new files, import and process them and at the end move them some place else.

 

There are 2 approaches:

  • First is to use FSO and OLE Automation
  • Second CLR integration

 

I decide to implement the second solution because:
  • is very hard to work with OLE automation
  • if the COM object executes in SQL Server address space, a bug in your code will crash SQL Server

 

VB.NET code
Imports System.IO
Imports System.Security.Permissions

<IODescriptionAttribute("SQLServerFileSystemWatcherDesc")> _
<PermissionSetAttribute(SecurityAction.InheritanceDemand, Name:="FullTrust")> _
<PermissionSetAttribute(SecurityAction.LinkDemand, Name:="FullTrust")> _

Public Class Import
<PermissionSet(SecurityAction.Demand, Name:="FullTrust")> _
<Microsoft.SqlServer.Server.SqlProcedure()> _
Public Shared Sub Arhive(ByVal sourcePath As String, ByVal fname As String, ByVal destPath As String)
File.Move(finalSource & fname, finalDest & fname)
End Sub
End Class
Code is compiled like this from command prompt:
vbc /t:library CAMAImport.vb

 

SQL Server side

 

Steps:
1) Enable CLR integration:

 

EXEC sp_configure @configname = 'clr enabled', @configvalue = 1
RECONFIGURE WITH OVERRIDE
GO

 

2)Register the assembly (please note PERMISSION_SET = EXTERNAL_ACCESS will never work wih SAFE! - took me an hour to figure out this):

 

CREATE ASSEMBLY WDMImport FROM 'c:\SQLServer\WDMLog\Import.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS
GO

 

3) Tell database server where to find the object code:

 

CREATE PROC ImportMoveFile
(@sourcePath NVARCHAR(255), @fname NVARCHAR(255), @destPath NVARCHAR(255) )
AS EXTERNAL NAME WDMImport.Import.Arhive
GO

 

4) Run it:

 

EXEC ImportMoveFile 'c:\', 'test.txt', 'c:\Imported\'