Showing posts with label VB. Show all posts
Showing posts with label VB. Show all posts

Tuesday, 21 June 2016

Having a standalone RadImageManager

The Telerik RadImageManager is a handy control for uploading / managing and selecting images, however it is embedded into the Rich Text editor control (RadEditor). To use it as a standalone tool you can use the following method:

In the front end view do the following:
  1. Add into Web.Config the telerik dialog handler declaration
  2. Declare a RadDialogOpener
  3. Declare a hidden field to store the domain path to be used in the URL
  4. Declare a textbox to store the URL
  5. Create an image icon to launch the Image Manager.
Add the following into the Web.config file:

<system.web>
    <httpHandlers>
     ....
      <add path="Telerik.Web.UI.DialogHandler.aspx" verb="*" type="Telerik.Web.UI.DialogHandler, Telerik.Web.UI"/>
    </httpHandlers>
</system.web>


Additional code in the aspx file:

<telerik:RadDialogOpener runat="server" ID="dop1" />
<asp:HiddenField ID="hfImageServer" runat="server" ClientIDMode="Static" />

<asp:TextBox ID="tbxImageURL" runat="server" Width="500" Text='<%#Bind("ImageURL")%>' MaxLength="256" ClientIDMode="Static" />
<img src="/images/icon/photo.png" onclick="$find('<%= dop1.ClientID %>').open('ImageManager', {CssClasses: []});return false;" width="16" height="16" alt="Image Manager for Image URL" title="Image Manager" />


In the code behind set up a function to initialise the Image Manager with appropriate property values. This can be reused for multiple Dialog Openers

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

Private Sub SetupImageManager(ByVal dop As RadDialogOpener)
  hfImageServer.Value = "http://www.mydomain.com"

  Dim imageManagerParameters As New FileManagerDialogParameters()
  imageManagerParameters.ViewPaths = New String() {"~/UploadFolderName"}
  imageManagerParameters.UploadPaths = New String() {"~/UploadFolderName"}
  imageManagerParameters.DeletePaths = New String() {"~/UploadFolderName"}
  'imageManagerParameters.MaxUploadFileSize = 102400
  'imageManagerParameters.SearchPatterns = new string[] { "*.jpg" };

  Dim imageManager As New DialogDefinition(GetType(ImageManagerDialog), imageManagerParameters)
  imageManager.ClientCallbackFunction = "ImageManagerFunction" & dop.ID
  imageManager.Width = Unit.Pixel(600)
  imageManager.Height = Unit.Pixel(500)
  imageManager.Parameters("ExternalDialogsPath") = "~/ExternalDialogs/"

  dop.DialogDefinitions.Add("ImageManager", imageManager)

  Dim imageEditorParameters As New FileManagerDialogParameters()
  imageEditorParameters.ViewPaths = New String() {"~/UploadFolderName"}
  imageEditorParameters.UploadPaths = New String() {"~/UploadFolderName"}
  imageEditorParameters.DeletePaths = New String() {"~/UploadFolderName"}
  'imageEditorParameters.MaxUploadFileSize = 102400

  Dim imageEditor As New DialogDefinition(GetType(ImageEditorDialog), imageEditorParameters)
  imageEditor.Width = Unit.Pixel(600)
  imageEditor.Height = Unit.Pixel(500)
  dop.DialogDefinitions.Add("ImageEditor", imageEditor)
End Sub

In the Javascript file have a callback function to populate the text field value

function ImageManagerFunctiondop1(sender, args) {
    if (!args) {
        alert('No file was selected!');
        return false;
    }
    var txt = $get('tbxImageURL');
    var path = args.value.getAttribute("src", 2);
    txt.value = $('#hfImageServer').val() + path;
}

Tuesday, 31 May 2016

DataBinding issues with a NULL or archived value

When binding web form controls to a data source you can often come unstuck when NULL values get returned from the database and you get dreaded run time NullReferenceExceptions. Although the examples below use Telerik controls, the equivalent ASP.NET controls can also be addressed in a similar manner

Binding a NULLable boolean field to a checkbox

When binding a boolean value to a grid, the add form will fail if it is NULLable due to there being no '3rd' option on a checkbox to handle the NULL value. To get around this we must set a default value manually when calling the InitInsert command as follows

Protected Sub rgd_ItemCommand(sender As Object, e As Telerik.Web.UI.GridCommandEventArgs) Handles rgd.ItemCommand
    If (e.CommandName = RadGrid.InitInsertCommandName) Then
        e.Canceled = True
        Dim newValues As System.Collections.Specialized.ListDictionary = New System.Collections.Specialized.ListDictionary()
        newValues("BoolField") = False
        e.Item.OwnerTableView.InsertItem(newValues)
    End If
End Sub

 

 
Binding a NULLable lookup table to Dropdown 

If you have a lookup table bound to a DropDownList/RadComboBox in a FormView/FormTemplate, by default it cannot handle NULL values if you create a line item for that NULL value. However by specifying a particular unused numeric value (such as 0 in this context will rarely by used for a table ID)

<telerik:RadComboBox ID="rcbForeignKeyID" runat="server" DataSourceID="sqlForeignKey" DataTextField="Name"
 DataValueField="ID" AppendDataBoundItems="true" SelectedValue='<%#Bind("ForeignKeyID")%>'>
    <Items>
        <telerik:RadComboBoxItem Text="No value..." Value="0" />
    </Items>
</telerik:RadComboBox>


On the Form's LinqDataSource we can then handle the Inserting & Updating events to set that 0 value to nothing which equates to DB NULL

Protected Sub lds_Inserting(sender As Object, e As System.Web.UI.WebControls.LinqDataSourceInsertEventArgs) Handles ldsForm.Inserting
    Dim rec As TableType = e.NewObject
    If rec IsNot Nothing Then
        If rec.ForeignKeyID = 0 Then rec.ForeignKeyID = Nothing
    End If
End Sub

Protected Sub lds_Updating(sender As Object, e As System.Web.UI.WebControls.LinqDataSourceUpdateEventArgs) Handles ldsForm.Updating
    Dim rec As TableType = e.NewObject
    If rec IsNot Nothing Then
        If rec.ForeignKeyID = 0 Then rec.ForeignKeyID = Nothing
    End If
End Sub




Binding a value no longer in the DataSource to a GridDropDownColumn

When using a dropdown in the edit form of a RadGrid you often encounter the scenario where the grid row value no longer exists in the dropdown data source due to the record being archived or some such. In order to work around this, we can manually add the existing record to the top of the dropdown so the SelectedValue binding won't break.

The aspx code should look something like this for the column specification
        <telerik:GridTemplateColumn UniqueName="ID" HeaderText="Header" AllowFiltering="false" DataType="System.Int32">
          <ItemTemplate>
            <asp:Label ID="lblHeader" runat="server" Text='<%#Eval("Name")%>' />
          </ItemTemplate>
          <EditItemTemplate>
            <telerik:RadComboBox ID="rcb" runat="server" Skin="Sunset" SelectedValue='<%#Bind("ID")%>'
                            OnDataBinding="rcb_DataBinding" AppendDataBoundItems="true"
              DataSourceID="sqlList" DataTextField="Name" DataValueField="ID" />
          </EditItemTemplate>
        </telerik:GridTemplateColumn>


The first bit of code required is an event handler for the RadComboBox / DropDownList control to add in the extra list item with the current value as follows
    'Add in option for existing record in dropdown
    Protected Sub rcb_DataBinding(sender As Object, e As EventArgs)
        Dim rcb As RadComboBox = DirectCast(sender, RadComboBox)
        Dim rci As New RadComboBoxItem("-- Existing Record --", rcb.SelectedValue)
        rcb.Items.Insert(0, rci)
    End Sub


The next bit of code is required to populate the text label of this new record with the actual value as follows
    'Set the label of the existing
    Protected Sub grd_ItemDataBound(ByVal sender As Object, ByVal e As Telerik.Web.UI.GridItemEventArgs) Handles grd.ItemDataBound
        If (TypeOf e.Item Is GridEditFormItem And e.Item.IsInEditMode) Then
            Dim editItem As GridEditFormItem = CType(e.Item, GridEditFormItem)
            Dim strName As String = editItem.ParentItem.DataItem("Name")
            Dim rcb As RadComboBox = DirectCast(e.Item.FindControl("rcb"), RadComboBox)
            If rcb IsNot Nothing Then rcb.Items(0).Text = strName
        End If
    End Sub


Customising the LinqDataSource

Binding a data grid to a data source quickly is a sinch with a LinqDataSource and it can save a lot of time. However sometimes it doesn't quite cut it and you wished you could use all of its benefits but just change one little aspect. Well actually with a bit of tweaking you can do exactly that. Here are two cases that I've frequently used while building some quick prototypes.

Altering the fields that are sent to a LinqDataSource

The data that is sent or received for a LinqDataSource action may need to be altered for a number of reasons, such as:
  1. Altering the data sent in an update if the information is incorrect (e.g. a blank ("") field updating to a numerical field)
  2. Filling in extra information for an insert (e.g. a predetermined foreign key)
The code is implemented in the handler for the LinqDataSource action, this will either be Inserting, Updating, or Deleting as the event will need to happen prior to the action.  In the code, first create a variable of the table type, then select the specific field and change it as needed.

Altering an Insert Example:
In this case, a foreign key needs to be automatically filled in.  The foreign key is taken from the query string parameter of the URL.
Protected Sub LinqDataSource_Inserting(sender As Object, e As System.Web.UI.WebControls.LinqDataSourceInsertEventArgs) Handles LinqDataSource.Inserting
    Dim rec As WEB_Table = e.NewObject
    Dim field As String = Request.QueryString("Field")

    If rec IsNot Nothing Then
        rec.Field = field
    End If
End Sub



Using a Stored Procedure or more complicated query with a LinqDataSource

Sometimes you want to use all the handiness of the automated Insert, Update and Delete functions but use a select command that is too complicated to be handled by the basic features provided by the LinqDataSource control. In order to do this we just override the Select query in the Selecting event. Here is an example of how to inject a stored procedure as the select data source.

1. Create stored procedure for your SELECT that includes any other business logic you want in it
2. Add the stored procedure to the data context and if you want to turn off optimistic concurrency checks, set Update Check to Never for all properties in that table (can highlight them all to change all at once)
3. In code behind change Selecting event of LinqDataSource to set the e.Result = DC.StoredProcedure(Params).ToList()

Protected Sub lds_Selecting(sender As Object, e As System.Web.UI.WebControls.LinqDataSourceSelectEventArgs) Handles lds.Selecting
    Dim res = db.usp_StoredProcList(Param1, e.WhereParameters("ParentID")).ToList()
    e.Result = res
End Sub

4. Remove any Where clause from LinqDataSource (and any WhereParameters if you don't need them)
5. Use WhereParameter to get ParentID field into Selecting event for Detail Level tables - accessed via e.WhereParameters("ParentID")