How to manipulate a Windows Forms control from another thread and get return value via Invoke() method


I was working on a Windows Forms project and I had this requirement to basically do some manipulation on a TreeListView on the parent form (MainForm in this case) for which we already had a developed a method and also to get the return value back from it. To make life even easier, we needed to do this from a BackGroundWorker thread in this case. Now, the problem with Windows Forms controls is that they can’t be manipulated apart from the main thread, so I had to look for a work around of some sort. So here’s a little modified snippet of the code for your understanding:-

if (m.treeListView.InvokeRequired)
{
ra= (ReportData?)m.treeListView.Invoke(new Func<ReportData?>(
() => m.CreateDataforReport(“Rpt type”, false)));
//m is the main form’s reference!

}

So what I’ve done is that I passed the main form’s reference to the child form in the constructor and made the TreeListView and the CreateDataforReport public. Notice that I called CreateDataforReport method inside the Func<ReportData?> and not directly. This is what enables you to get the appropriate return value, be it string, integer or any complex type like I have it here.

SPGridView’s OnRowDataBound event returning nulls – Unable to FindControls


Earlier today I was just playing around with SharePoint 2010 and thought I should do a simple task with SPGridView, that is to display the data and show an appropriate image in the “Status” column instead of the text. Hmm, sounds quite simple doesn’t it! But no, it turned into a misery. Well, when I started it was quite natural to use the OnRowDataBound event on that to capture the data and do some modifications with the controls (I was using TemplateFields in the SPGridView by the way), so I did that and I tried  doing things like e.Row.FindControl(“xyz”), e.Row.Cells[2] and using RowIndex property which was returning -1 where e refers to an object of GridViewRowEventArgs and there was nothing to get over there. It was nulls all around!

So here’s a sample of the code in the visual webpart that I was writing:-

<SharePoint:SPGridView ID=”spGvWorkOrders”  runat=”server” >
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID=”lbl_workOrderId” Text='<% # Bind(“Id”) %>’  runat=”server”></asp:Label>
</ItemTemplate>
</asp:TemplateField>

<asp:TemplateField>
<ItemTemplate>
<asp:Label ID=”lbl_workOrderTitle”  runat=”server” Text='<% # Bind(“Title”) %>’ ></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>

<asp:Image ID=”img_status” Width=”10px” ImageUrl='<% #StatusToImage(“\””+ Eval(“Status”)+”\””) %>’ runat=”server” />
</ItemTemplate>
</asp:TemplateField>

And here is the function:-

protected string StatusToImage(string status)
{
if ( ( rowcount++ % 2) == 0)
return “~/_layouts/Images/WorkOrders/add.png”;
else
return “~/_layouts/Images/WorkOrders/arrow_up_green.png”;
}

Notice that I had been using the Bind function earlier but when I tried using it to send the value to StatusToImage function it did not work. Eval is the better option anyway in case you’re just interesting in displaying the data.

So what I did was that instead of using the event I just put the function call inside the ascx code so that whenever a row is created that function is called with the value of Status from the Data Source and with that value sent to a function, we can return back a string to give the path to the image file. The syntax however, is quite tricky and it took me a while to figure that out correctly but it worked in the end. Hope it will save you some time though!

How to remove ReadOnly Attribute from a file?


Hello friends,

Here’s a nice little piece of code you can use to change file attributes of a particular file, its particularly useful when you’re trying to delete a read only file.

string savedCardFilePath = “My absolute file path”;

if (File.Exists(savedCardFilePath))
{
/*
* Remove readonly attribute off of the file if it exists before execution
*
**/
if(File.GetAttributes(savedCardFilePath) == FileAttributes.ReadOnly)
File.SetAttributes(savedCardFilePath, FileAttributes.Normal);
File.Delete(savedCardFilePath);
}

 

UPDATE May 14, 2012:

There have been some problems reported and better solutions given on this article so I updated the code to:

FileAttributes attributes = File.GetAttributes(file);

if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
File.SetAttributes(file, attributes ^ FileAttributes.ReadOnly);

Thanks for the feedback and sorry about the mistake 🙂

 

 

How to make a file download on button click?


Ever wonder how you could put in the functionality of downloading a file when the user clicks the button? Well here’s how I did it. The technique is to send the file to the browser via response and put the content type to application/pdf. Without putting in any further delays, here’s the code.

/// <summary>
/// opens the specified file in the request when provided the correct content type
/// </summary>
/// <param name=”FileName”></param>
/// <param name=”ContentType”></param>
/// <param name=”SaveAsFileName”></param>
/// <param name=”response”></param>

public static void ResponseOpenFile(string FileName, string ContentType, string SaveAsFileName, HttpResponse response)
{

response.Clear();

response.AddHeader(“content-disposition”, “attachment;filename=” + SaveAsFileName);

response.ContentType = ContentType;

response.WriteFile(FileName);

response.End();

}

Thats how I call the method. This is being done in the on click event of the download button.

ResponseOpenFile(Server.MapPath(“../applications/”)+oApp[0].ApplicationID.ToString()+”.pdf”, “application/pdf”, “Application.pdf”, Response);

Happy Programming folks!

How to Add Shaded Rows to ListView’s Details View


Sometimes it can be challenging to read the Details view in a ListView, especially if the rows are long. This article shows how to add shading to every second row to make a ListView easier to read.

As you may know, you can alter the appearance of individual ListViewItem’s such as the Font and BackColor. But these values are ignored unless you set the item’s UseItemStyleForSubItems property to true.

The following code demonstrates how to shade every other row in a ListView:

ListView listView = this.ListView_Products;

listView.View = View.Details;

int i = 0;

Color shaded = Color.FromArgb( 240, 240, 240 );

foreach (Product product in products)

{

ListViewItem item = new ListViewItem( product.Name );

item.SubItems.Add( product.Version );

item.SubItems.Add( product.Description );

item.SubItems.Add( product.Status );

if (i++ % 2 == 1)

 {

item.BackColor = shaded;

item.UseItemStyleForSubItems = true;

}

listView.Items.Add( item );

}


VB .NET Code:-

Dim listView As ListView = Me.ListView_Products

listView.View = View.Details

Dim i As Integer = 0

Dim shaded As Color = Color.FromArgb(240, 240, 240)

For Each product As Product In products

    Dim item As New ListViewItem(product.Name)

    item.SubItems.Add(product.Version)

    item.SubItems.Add(product.Description)

    item.SubItems.Add(product.Status)

    If System.Math.Max(System.Threading.Interlocked.Increment(i),i – 1) Mod 2 = 1 Then

        item.BackColor = shaded

        item.UseItemStyleForSubItems = True

    End If

    listView.Items.Add(item)

Next

Properties in .NET


Property in C#:

Property ? it is a special method that can return a current object?s state or set it. Simple syntax of properties can see in the following example:

public int Old 
{
   get {return m_old;}
   set {m_old = value;}
 } 
public string Name 
{
   get {return m_name;} 
}

Here are two types of properties. A first one can set or get field of class named m_old, and the second is read only. That?s mean it can only get current object?s state.

The significance of these properties is its usability. These properties need not be called with any function names like objectname.get or objectname.set etc., But they can be directly assigned the values or retrieve the values.

The VB .NET Syntax of declaring a property is as follows:-

Public Property X() As Integer
Get
     Return
x
End
Get
Set(ByVal Value As Integer
)
     x = value
End
Set
End Property

how to redirect the page when Session Expires?


I read this on http://forums.asp.net/t/1137344.aspx
when I was modifying a Global.asax file that had Response.Redirect written in its Session_End Event. I guess the programmer aimed to redirect the application to the error page like this but the fact is that u dont have the Response Object in this particular event, the reason being that it’s fired internally by the server when the session gets expired. As an alternate to that I read this post post on the above mentioned URL, it suggests that we should use a BasePage and add this code in its PageLoad event. This way the meta info will be added to all the pages that inherit from this BasePage and they will redirect after 5 seconds of the Session timeout.

I think its quite brilliant, so hats off to ya!

HI, anilperugu: The easiest way what I feel is to use Meta information and get the trick working. Consider we have a page WebPage.aspx add the below code in the the WebPage.aspx.cs file.

private void Page_Load(object sender, System.EventArgs e)
{

Response.AddHeader(“Refresh”,Convert.ToString((Session.Timeout * 60) + 5));
if(Session[“IsUserValid”].ToString()==””)
Server.Transfer(“Relogin.aspx”);

}

In the above code, The WebPage.aspx is refreshed after 5 seconds once the Session is expired. And in the page load the session is validated, as the session is no more valid. The page is redirected to the Re-Login page. Every post-back to the server will refresh the session and the same will be updated in the Meta information of the WebPage.aspx.
Best Regards,
Sincerely,
Rex Lin
Microsoft Online Community Support