Recently, I was working on a project that had half its code developed using .Net 1.1 framework while the other half developed using .Net 3.5. Though the pieces worked independently, a few windows services written in .Net 1.1 required an assembly generated at runtime. Now this assembly was being generated from the web site (previously written in .Net 1.1 framework), which now was re-written using 3.5.
This was a problem, because the .Net 3.5 code could compile code at run time targeting either 2.0 or the 3.5 framework. Since the services written in 1.1 required an assembly to be compiled in 1.1, it could not load the assembly that was being generated.
A bit of research and the use of .Net Reflector tool, provided the solution.
Lets start with the code that will compile an assembly at runtime using code written in a text file targeting .Net 3.5 framework.
Dim Compiler As VBCodeProvider = Nothing Dim pvdr As CodeDomProvider Dim CompilerParams As CompilerParameters Dim CompileResults As CompilerResults
Public Function CompileCode() As String Dim strReturn As String = "" Try CompilerParams = New CompilerParameters With CompilerParams .TreatWarningsAsErrors = False .WarningLevel = 4 .GenerateInMemory = False .IncludeDebugInformation = True
Dim References() As String = {"System.dll", "System.Data.dll", "Microsoft.VisualBasic.dll"} .ReferencedAssemblies.AddRange(References) .OutputAssembly = "C:\Projects\ThisIsATestDLL.dll"
End With
Dim provOpt = New Dictionary(Of String, String) provOpt.Add("CompilerVersion", "v3.5") Compiler = New VBCodeProvider(provOpt)
If CompileResults.Errors.HasErrors Then For Each Err As CodeDom.Compiler.CompilerError In CompileResults.Errors strReturn &= Err.ErrorText & " @Line: " & Err.Line & vbCrLf Next End If
Catch ex As Exception Throw New Exception(ex.Message, ex) End Try Return strReturn End Function
That is the key. If we switch this to
provOpt.Add("CompilerVersion", "v2.0")
Our code will compile in version 2.0 framework.
What we want is to comile in 1.1. It is not as simple as changing the version to say "v1.1". That wont work. To understand how to accomplish this, we have to look at the code of VBCodeProvider's constructor. I used the .Net reflector to take a look at this.
The CodeDOMCompiler code does the following
If version is 3.5 then look at the environment variables. If environment variables COMPLUS_InstallRoot and COMPLUS_Version is not present then compile code to default 3.5 version. Else read those environment variable versions to do the compile. If the version is not 3.5 then it is defaulted to 2.0.
As you can see, the only two values that can be passed to the VBCodeProvider's constructor is "v3.5" or "v2.0".
So in order to compile the assembly in 1.1, we will introduce the env variables in code.
Public Class CodeCompiler Dim Compiler As VBCodeProvider = Nothing Dim pvdr As CodeDomProvider Dim CompilerParams As CompilerParameters Dim CompileResults As CompilerResults
Public Function CompileCode() As String Dim strReturn As String = ""
Try CompilerParams = New CompilerParameters With CompilerParams .TreatWarningsAsErrors = False .WarningLevel = 4 .GenerateInMemory = False .IncludeDebugInformation = True
Dim References() As String = {"System.dll", "System.Data.dll", "Microsoft.VisualBasic.dll"} .ReferencedAssemblies.AddRange(References) .OutputAssembly = "C:\Projects\ThisIsATestDLL11.dll"
End With
'You can put these values in the config file if you dont want to 'hard code it. Environment.SetEnvironmentVariable("COMPLUS_InstallRoot", "C:\WINDOWS\Microsoft.NET\Framework") Environment.SetEnvironmentVariable("COMPLUS_Version", "v1.1.4322")
Dim provOpt = New Dictionary(Of String, String) provOpt.Add("CompilerVersion", "v3.5")
Compiler = New VBCodeProvider(provOpt) CompileResults = Compiler.CompileAssemblyFromFile(CompilerParams, "C:\RandD\VS08\TestClassLib\Test.vb")
If CompileResults.Errors.HasErrors Then For Each Err As CodeDom.Compiler.CompilerError In CompileResults.Errors strReturn &= Err.ErrorText & " @Line: " & Err.Line & vbCrLf Next End If
Catch ex As Exception Throw New Exception(ex.Message, ex) End Try Return strReturn End Function End Class
does the trick. It foxes the .Net code into believing that we have 3.5 version to be compiled, but since we introduce the env variables before calling the VBCodeCompiler's constructor, it will read the env variables and compile the code in 1.1. It's that simple.
These env variable setting is only for that current code and once the code runs out of scope, the env variables are not persisted.
I had posted this solution on www.experts-exchange.com too.. Hope it helps someone!
So I have searched, re-searched (pun intended) to find an acceptable solution where I am able to do the following,
1. Enable mouseover and mouseout on a Data Grid View control in ASP.Net
2. Enable Multiple Clickable rows and Single click rows on a grid view control.
3. And access a key data from the row that has been clicked.
Now instead of writing server side code and attaching a ton of javascript at each row creation along with a lot of data, I finally did something with JQuery and Javascript. It works like a charm. Ofcourse, you can all tinker with the code and make the code better... so let me know how it all went!
So let's get our hands dirty. (I am obviously assuming you have a test page, with a gridview control on it and a web project created... if not please do that, else reading this would be pointless... ;-D)
STEP1
1. Create a stylesheet and name it.. I dont know, name it something.. maybe styles.css
2. Add the following items to it. This is what we will use to style our grid view. Ofcourse you can use your own styles. The key thing to remember is to have a Pager class if you have paging setup for your grid and a style for tag so that the header is styled too. The pager is important.
Save your stylesheet and create a new file and name it HoverScript.js. We will add our JQuery and Javascripts here and add the following code into the HoverScript.js file and save it.
var PrevRow;//Stores the last clicked row
var NewRow;//Gets the new row clicked
var RowClickedValue = '';//Stores a comma separated value of the items clicked
var CurrentRowClicked = ''; //Gets the value of the row that has been clicked
var GridPlainHover = '#add8e6'; //Some styling
var GridPlainClicked = '#ffff99'; //Some styling
var GridPlainNeutral = 'white'; //Some styling
var sSkipHeaderFooter = ''; //Tracks whether the Header and Footer will be skipped
var CancelClick = false;
var hdnClickedValues = '';
//This is the function that will set all the hover and click functions.
//The function takes the ClientID of the grid for which the rules will be set
//boolean flags to say if Mulitple clicks should be allowed, If a Header is
//included in the Grid and if a footer is included in the grid. We dont want
//to hover over the Header and footer.
function fn_SetHoverRules(sGrid, bMultiClick, bIncludeHeader, bIncludeFooter) {
In my example, I am using a Gridview control with paging setup. For the purpose of explaining how to do the setup, I have my gridview retrieving information from an Employees table. The key item I will be associating with the Row Click is the “Employee ID” which I will use to perform the required operations. For example, select Multiple Employee rows and click Delete or Select Multiple Employee rows and click a Process button .etc.
Obviously, you will have your own Gridview control with your own Bound or unbound columns. So feel free to modify it the way you want. A few things to remember (and I take the liberty in the assumption)..
The Gridview will have a CSS class as “GridClass”.
If there is a pager, it’s class will be set to “pager” CSS class.
The unique id for each row will be associated with the FIRST VISIBLE COLUMN. Now this is important. For the code above to work correctly, it is assuming that the first visible column of the grid has the id that will be retrieved and stored when the user clicks on the row. If you ommit this step, the javascript will fail to retrieve the id. You can modify that piece get it from whichever column you set the unique key to.
Based on these conditions and assumptions, add a Gridview to your aspx page
I am not going to add the code to retrieve the data from the database and bind it to the grid. You do that. Now once you have done that in your code behind, go to the RowDataBound event of the Gridview and add the following lines of code.
PrivateSub gdvEmployees_RowDataBound(ByVal sender AsObject, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gdvUnknownErrors.RowDataBound
'Get the current instance of the Row being bound
Dim GridRow As GridViewRow = e.Row
'Make sure this is a row and not a Header or a Footer
If GridRow.RowType = DataControlRowType.DataRow Then
'Create an instance of the DatarowView from the DataItem being bound
Dim DRV As DataRowView = CType(e.Row.DataItem, DataRowView)
'Make sure we have a Emp_ID
IfNot IsDBNull(DRV("Emp_ID")) Then
'Assign the Id attribute to the first visible column, in our case it will be Date Inserted
That’s it. Run your web page and see it all come together. I have shown you how you can do the following
Use JQuery to perform Mouse over, Mouse Out and Click on a Grid view control.
Skip Header and Footer from mouse over and mouse out and click while using JQuery to perform that operation.
Retrieve the clicked values in your code behind.
Hope this is helpful to anyone looking for it. I am not including any code for this, it is upto you to put it all together and make it work. Comments are most welcome and I will answer any questions or issues you might have doing this.