Using resource files in embedded user controls in skins
If you are editing ASCX skins, then you have probably been tempted to introduce a bit of reusability by creating custom user controls and embedding them to your skins. These can actually function like skin objects, but without all the fuss. I’ve found it easy to create a couple of those in cases where I may need, for example, a common footer for all my skins, but of course you can do a great deal more with them, like introduce functionality without having to copy all the code to every skin file you make.
In any case, you have to register your control inside your skin file like this (names of folders, portal and skin path and tagprefix/name are arbitrary):
<%@ Register TagPrefix="MyCompany" TagName="FOOTER" src="~/Portals/0/Skins/myskin/myskinobjectsfolder/footer.ascx" %>
And use it in your skin file like this:
<MyCompany:FOOTER id="myFooterId" runat="server" />
The question is: How do you localize these little bastards? Even if you add DNN controls on them, the ResourceKey property continues to get data only from the skin’s resource file, not the control’s.
Of course, you can use your skin’s resource file to get localized strings and other data but this isn’t very convenient since you’ll have to add data to every resource file corresponding to each one of your skins. And I’m not going to talk about app_globalresources either! :)
(If you don’t know that you can have resource files for your skins, yes, you can. You can have a skins/app_localresources folder and you can have .resx files there and you can use the ResourceKey attribute in your DNN control tags to get localized data for your controls in your skins).
Well, based on this excellent post here about localizing embedded controls, I thought it would be good to summarize and simplify the process a bit. So here it goes:
You can give an embedded user control its own resource file by following two different approaches:
1. Make it inherit PortalModuleBase
2. Specify the resource file yourself and make the control use it.
Approach 1: Inheriting PortalModuleBase
You just have to add:
Inherits="DotNetNuke.Entities.Modules.PortalModuleBase"
in your control’s header.
E.g.
<%@ Control language="vb" AutoEventWireup="false" Explicit="True" Inherits="DotNetNuke.Entities.Modules.PortalModuleBase" %>
Doing so will give you access to the LocalResourceFile property, which will in turn point to the .resx file located in the app_localresources folder right under your control’s location.
But what .resx file, exactly? Not the one you expected.
The resx file will NOT follow the file name of your user control, but the ID by which it is called. If your control’s filename is MyFooter.ascx, and you call it with an ID of “myFooterId” then your resource file must be named “myFooterId.ascx.resx”.
Then, you can use code like this to get a localized value, for example, for the “Footer.Text” key:
<%=DotNetNuke.Services.Localization.Localization.GetString("Footer.Text", LocalResourceFile)
%>
Ugly, because you have to remember to always use the same ID and also because you can’t use two instances of your control in the same skin. Also, inheriting PortalModuleBase restricts your coding flexibility.
Approach 2: Forcing the user control to use a resource file
If you don’t want your user control to inherit PortalModuleBase but you still need it to have its own resource files, you can define a LocalResourceFile property yourself. This is written directly in the .ASCX file but, of course, you can put it in code-behind too. (sorry about the line breaks):
<script runat="server">
Public ReadOnly Property LocalResourceFile As String
Get
Return Me.TemplateSourceDirectory & _
"/" & _
DotNetNuke.Services.Localization.Localization.LocalResourceDirectory & _
"/" & _
System.IO.Path.GetFileNameWithoutExtension(me.AppRelativeVirtualPath)
End Get
End Property
Public Function GetLocalizedString ( _
ByVal key as string) as string
Dim retVal as String
retVal = _
DotNetNuke.Services.Localization.Localization.GetString( _
key, LocalResourceFile)
return (retVal)
End Function
</script>
What we did here was to create our own LocalResourceFile property. This tells the control to use a resource file that follows the file name of the control itself. So, if your control is named footer.ascx, your resource file will lie in app_localresources\footer.ascx.resx. If you need to specify a differently – named resource file, you just replace the GetFileNameWithoutExtension call with your own string. E.g. if you use “myownFooter” there, then there must be a myownFooter.ascx.resx file in the app_localresources folder.
In addition, we created a GetLocalizedString function which will just take the key and return the string from the resource file.
We can use this function in our user control to get localized data as follows:
<%=GetLocalizedString("Footer.Text")%>
This is much simpler and much more flexible.
Read more...