Thursday, October 6, 2011
Sunday, September 25, 2011
Center Text AND Images Within ASP .NET
I recently integrated the handy AddThis sharing and analytics tool into an ASP .NET site I'm working on.
Whether due to peculiarities of the markup or browser idiosyncrasies, I couldn't get the widget consistently centered. The widget code lives in a div tag, and despite a popular few suggestions, I simply couldn't get things centered horizontally.
Centering text is no big deal; simply applying a CSS style usually does this well enough:
Images, however, aren't accounted for by this markup.
I ended up enclosing the widget in a Table control with the HorizontalAlign attribute specified to "Center", and this did the trick.
Much easier to allow ASP .NET to handle the grunt work of emitting the necessary markup in this case than messing (directly) with styles.
Whether due to peculiarities of the markup or browser idiosyncrasies, I couldn't get the widget consistently centered. The widget code lives in a div tag, and despite a popular few suggestions, I simply couldn't get things centered horizontally.
Centering text is no big deal; simply applying a CSS style usually does this well enough:
text-align: center;
Images, however, aren't accounted for by this markup.
I ended up enclosing the widget in a Table control with the HorizontalAlign attribute specified to "Center", and this did the trick.
![]() |
Centered! |
Much easier to allow ASP .NET to handle the grunt work of emitting the necessary markup in this case than messing (directly) with styles.
Wednesday, September 14, 2011
Assembly must be Strong Signed in order to be marked as a Prerequisite
In the process of trying to update and rebuild a C# project utilizing Microsoft's Enterprise Library, I inexplicably got the error "Microsoft.Practices.EnterpriseLibrary.Data.dll must be strong signed in order to be marked as a prerequisite."
I hadn't touched this project in a while, in fact I may've last built it on a different PC, so I guess if I had strong signed the Enterprise Library dll, the new system had no idea. Also, I'd installed .NET 4 recently, so maybe this had something to do with this earlier version of the Enterprise LIbrary (my project implements 4.1 whereas the latest version is 5). I guess security in the .NET 3.5 framework isn't up to snuff as far as .NET 4 is concerned.
Anyway, it appeared I had no choice but to use the sn.exe utility and create a key pair and do all the stuff Microsoft suggests in their painfully tedious article on how to sign an assembly with a strong name. Luckily after some digging I found Signer, a command-line utility which simplifies the process of strongly signing one or more assemblies which VS 2008 may be complaining about.
I'm referencing this from the perspective of a Windows 7 64-bit system, so note that the following may vary if you're using 32-bit.
In order to do it's thing, Signer requires access to some other command line utilities, most of which live in C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\. A few, however, including ilasm.exe and fusion.dll, live elsewhere (in my case, these were hanging out in C:\Windows\Microsoft.NET\Framework64\v4.0.30319).
I decided to copy Signer.EXE to the above SDK path, and copy the latest versions of the above files to that same path, so that when I execute Signer.EXE, it'll be able to easily find all the external EXE and DLL files in the same directory.
First of all, though, I needed to use MIcrosoft's sn utility to create an .snk key file in my SDK folder from a command prompt as follows:
sn.exe -k 1024 myProjectKeyName.snk
This instructs sn to produce a key file named myProjectKeyName.snk which I really don't care about for anything other than getting my project to build again. Thus, I chose an arbitrary key file name and value of 1024-bit key length.
I then executed Signer as follows in the same folder:
signer.exe -k myProjectKeyName.snk -outdir C:\myProject\myProjectLibrary -a C:\myProject\myProjectLibrary\*.dll
Here I'm instructing Signer to take the key I just created and strongly sign all .DLL files in my project's library folder. After this, I did a Clean Build on my project, then a Build, and thank goodness, the build completed successfully!
Even though Visual Studio 2008 can't build .NET 4 applications, I guess nevertheless since I have the .NET 4 framework installed, it's mandated that all assemblies shall be strong signed, or the project using them shall not build. Whatever, I'm just happy to have gotten past this issue.
Labels:
.Enterprise Library,
ASP.NET,
C#,
visual studio 2008
Monday, September 12, 2011
Google-like Filtering with RadGrid and Separate Data Class
I needed
to create a Google Suggest style
search interface for an ASP.NET
page.
Our site
recently obtained licenses to the Telerik control suite, and the powerful RadGrid control looked like it was just
what I needed. I found this
example on the Telerik site.
Key to
this setup is having a textbox for
the user to input filter criteria, which is then from the user's perspective transformed into a RadComboBox object to house matching
results; then once the user selects an item from the dropdown, the RadGrid is bound and displays any matching
results.
I
encountered a problem because our site uses a centralized class library for CRUD
outside of this particular page’s code class, meaning I could not access my
application’s data context from within the GridBoundColumn class definition. The
Telerik example (specifically in the MyCustomFilteringColumnCS.cs
file) performs its own queries as needed using a SqlDataAdapter with a ConnectionString
obtained from the application configuration. A simple SELECT statement is executed which returns matching results.
When I
tried to reference my centralized data class from within the GridBoundColumn class definition, I got
the following error:
Cannot
access non-static property … in static context.
protected void list_ItemsRequested(object o, RadComboBoxItemsRequestedEventArgs e)
{
// Cannot access non-static property 'CurrentUser' in static context.
using (MyCRUD mc = new MyCRUD(CurrentUser) )
{
{
((RadComboBox)o).DataTextField
= DataField;
((RadComboBox)o).DataValueField
= DataField;
((RadComboBox)o).DataSource
= mc.GetMatchingAddresses(e.Text);
((RadComboBox)o).DataBind();
}
}
My GridBoundColumn class does not exist
until my application instantiates it with its parent RadGrid object, so I cannot directly
assign a property to it. However, I stumbled upon this post which made me
realize I could, in the GridBoundColumn class definition, make several changes.
- Define a constructor for the class which takes an existing instance of the MyCRUD class as input.
- Create a public property in the class definition which can be assigned the MyCRUD object.
- Create a private field in the class definition to contain the instance of the MyCRUD object to be utilized by the GridBoundColumn class.
Below is
the modified class, with additions (*) indicated below.
public class rgcFilterColumn : GridBoundColumn
{
// * I added a constructor with an input parameter of the type
// * corresponding to my app’s CRUD object.
public
rgcFilterColumn(MyCRUD mycrud)
{
TheDataContext = mycrud;
}
// * This field provides an
instance of the rgcFilterColumn class
// * with the corresponding value set for the data
context object.
private
readonly MyCRUD
TheDataContext;
// * This property enables
the process which instantiates this
// * class to assign the MyCRUD object to
TheDataContext.
public
MyCRUD thedatacontext
{
get
{ return TheDataContext; }
}
// RadGrid will call this method when it initializes
// the controls inside the filtering item cells
protected
override void
SetupFilterControls(TableCell cell)
{
base.SetupFilterControls(cell);
cell.Controls.RemoveAt(0);
RadComboBox
combo = new RadComboBox
{
ID = ("RadComboBox1" + UniqueName),
ShowToggleImage = false,
Skin = "Office2007",
EnableLoadOnDemand = true,
AutoPostBack = true,
MarkFirstMatch = true,
Height = Unit.Pixel(100)
};
combo.ItemsRequested +=
list_ItemsRequested;
combo.SelectedIndexChanged +=
list_SelectedIndexChanged;
cell.Controls.AddAt(0, combo);
cell.Controls.RemoveAt(1);
}
// RadGrid will call this method when the value should
// be set to the filtering input control(s)
protected
override void
SetCurrentFilterValueToControl(TableCell
cell)
{
base.SetCurrentFilterValueToControl(cell);
RadComboBox
combo = (RadComboBox)cell.Controls[0];
if
((CurrentFilterValue != string.Empty))
{
combo.Text =
CurrentFilterValue;
}
}
// RadGrid will call this method when the filtering value
// should be extracted from the filtering input control(s)
}
}
// RadGrid will call this method when the filtering value
// should be extracted from the filtering input control(s)
protected
override string
GetCurrentFilterValueFromControl(TableCell
cell)
{
RadComboBox
combo = (RadComboBox)cell.Controls[0];
return
combo.Text;
}
protected
void list_ItemsRequested(object o, RadComboBoxItemsRequestedEventArgs
e)
{
// * Below we use the value of field
TheDataContext to execute
// * a method accesible via the MyCRUD data context for the
application.
using (MyCRUD mc = TheDataContext)
{
((RadComboBox)o).DataTextField
= DataField;
((RadComboBox)o).DataValueField
= DataField;
((RadComboBox)o).DataSource
= mc.GetMatchingAddresses(e.Text);
((RadComboBox)o).DataBind();
}
}
private
void list_SelectedIndexChanged(object o, RadComboBoxSelectedIndexChangedEventArgs
e)
{
GridFilteringItem
filterItem = (GridFilteringItem)((RadComboBox)o).NamingContainer;
if
((UniqueName == "Index"))
{
//
this is filtering for integer column type
filterItem.FireCommandEvent("Filter",
new Pair("EqualTo", UniqueName));
}
//
filtering for string column type
filterItem.FireCommandEvent("Filter", new
Pair("Contains",
UniqueName));
}
}
Now an instance of the GridBoundColumn class can happily utilize my application's central CRUD class for all its data retrieval operations.
Subscribe to:
Posts (Atom)