displaying multiple ascx in dotnetnuke - dotnetnuke

I am a newbie programming modules for dotnetnuke.
At this moment I use only the view.ascx for displaying my logic.
I need to display different views based on the login user and the attach user role. I can do it by setting some of the controls visible and non visible but I think it is not the right way and make the code unnecessary complex.
I came across an earlier question in stackoverflow (DNN: Using multiple web user controls in one module and showing different controls in different pages)
But have still some questions:
I have to add a new webformuser control in vs2013 when I want to design a new view in a seperate ascx?
I think the solution mentioned in the link using a placeholder will solve my question. But which steps do I need to transform my current solution with "view.ascx" to a solution with a placeholder?
I need to create first a new webusercontrol and named it "MasterControl.ascx" and put the placeholder control in it?
I need to create additionally for each view a new webusercontrol? What about the view.ascx? I dont need it anymore? What is the controlpath? Is it the path where the user control reside?
Is this the following layout:
MasterControl.ascx calling
userview1.ascx
userview2.ascx
...
userviewk.ascx
How to register "MasterControl.ascx"? I dont see "add control" in my current module when edited? I used DNN 7.2.x with the Cristoc addin.
I have to replace child1 wirh userview1 etc? When I supply the condition the corresponding userview.ascx will be displayed?
I a am a complete newbie so I need a step by step "cookbook recipe" how to convert my current module with, only using, a one "view.ascx" approach with a more flexible multiple ascx solution.
Thanks in advance,
Regards,
Henk
a copy of the code mentioned in the above link.
string childControl;
switch (condition)
{
case "condition1":
childControl = ControlPath + Child1.ascx";
break;
case "condition2":
childControl = ControlPath + Child2.ascx";
break;
...more conditions...
}
PortalModuleBase objModule = (PortalModuleBase)this.LoadControl(childControl);
if ((objModule != null))
{
myPholder.Controls.Clear();
objModule.ModuleConfiguration = this.ModuleConfiguration;
myPholder.Controls.Add(objModule);
}

If you only have a few things to hide or show then you could make use of <asp:Panels>. You could the set the visibility depending on a calculated property or some other logic; for instance, I have used the IsSuperUser property.
ASCX file:
<asp:Panel id="pnlSomeDeclarativeCode" runat=server>
<h1>Hide or show me</h1>
</asp:Panel>
In your codebehind file:
private Initialise()
{
pnlSomeDeclarativeCode.Visabilty = UserInfo.IsSuperUser;
}

Related

How to handle Solutions, Projects and their contents in a VisualStudio extension

In short:
I'm new to VisualStudio Extensibility and my goal is to create an extension with a ToolWindow (which already works) showing different views for each context of a VisualStudio solution, i. e. a view for the solution, a view for a project etc.. The window should be opened by clicking on a context menu entry in the context menus of the Solution Explorer, Class View, Object Browser and (ideally) any other window showing contents like projects, namespaces, classes etc..
After searching I found a lot of information, but for some points I couldn't find very helpful information. How do I ...
... create a context menu item for the VisualStudio views?
... get the currently open solution as an instance in code?
... get the projects of the solution and their contens as instances in code?
... add/remove items to/from a solution/project/class/... in code?
... react to selection changes in the Solution Explorer?
What I've done, so far:
I read the docs for Starting to Develop Visual Studio Extensions and downloaded the VSSDK-Extensibility-Samples. Especially the WPF_Toolwindow example was interesting for my purposes, so I built and ran it, which was successful, so far. Another interesting sample would have been the WPFDesigner_XML, but it always throws a NullReferenceException, so I decided to stick with the former ToolWindow, which is completely fine, for now.
Furtermore, I tried to understand the example by having a close look at each file in the project, running it in the debugger and analyzing what happened. I'm confident I understood it, but am also open for corrections of my possibly misguided thoughts following.
Now, I have created a new project, based on the WPF_Toolwindow sample, renamed and adapted to my needs (basically, I created new GUIDs, renamed the namespaces and removed things I won't use). This extension still works in the debugger. I even uninstalled everything from the experimental instance and debugged the extension from scratch.
What I try to achieve:
Have the ToolWindow load a specific view/viewmodel, when the selection changes in the Solution Explorer (or any other VisualStudio view). Alternatively, there should be a context menu item for every node's context menu in the Solution Explorer tree (or any other VisualStudio view).
Get the currently open solution, the containing projects and basically everything from the Solution Explorer's content as instances processable in my viewmodel. I need to properly add/remove
classes/structs/enums to/from
a folder in a project
a namespace
properties/fields to/from a class/struct
Generate code based on information of the solution and add the file properly to a project.
Does anyone know of examples for something like this or can anyone give me some hints, where I can find further information? Any help would be appreciated. Thanks in advance.
(1) The items already have a context menu and I want to add a new command to this menu.
if you want to add a sub menu to the context menu, the following link provide a complete sample
https://github.com/visualstudioextensibility/VSX-Samples/tree/master/CommandSubmenu
(3) Yes, basically adding a file to a project without manually manipulating the project file would be nice.
You can add the file to project via Project.ProjectItems.AddFromFile, and the following provide a sample for your reference.
https://www.mztools.com/Articles/2014/MZ2014009.aspx
Update:
I select a project and a similar event is fired. Are there such events I can subscribe to?
You could use IVsMonitorSelection to implement. here is the code which retrieve related project path for your reference.
IntPtr hierarchyPointer, selectionContainerPointer;
Object selectedObject = null;
IVsMultiItemSelect multiItemSelect;
uint projectItemId;
IVsMonitorSelection monitorSelection =
(IVsMonitorSelection)Package.GetGlobalService(
typeof(SVsShellMonitorSelection));
monitorSelection.GetCurrentSelection(out hierarchyPointer,
out projectItemId,
out multiItemSelect,
out selectionContainerPointer);
IVsHierarchy selectedHierarchy = Marshal.GetTypedObjectForIUnknown(
hierarchyPointer,
typeof(IVsHierarchy)) as IVsHierarchy;
if (selectedHierarchy != null)
{
ErrorHandler.ThrowOnFailure(selectedHierarchy.GetProperty(
projectItemId,
(int)__VSHPROPID.VSHPROPID_ExtObject,
out selectedObject));
}
Project selectedProject = selectedObject as Project;
string projectPath = selectedProject.FullName;
For more information about the usage, please refer to:
https://www.mztools.com/articles/2007/mz2007024.aspx

Form subclasses in codename one

I'm building an app in Codename one. I'm trying to both create a Form in the codename one resource GUI and specify its type used in code. Background is to be able to specify dynamically which data is used in the form.
Is this recommended and is there a recommended way to accomplish that?
Currently I'm digging into the codenameone code and it looks like one way would be to pass a custom-made resource to the StateMachine/UIBuilder. The UIBuilder asks the resource for the component type and use this to return a custom type,
and register the custom form types with lines like
UIBuilder.registerCustomComponent("MyForm",com.myapp.MyForm.class);
Any suggestions to this?
Right now the only way to do this in the old GUI builder is to replace all the forms with your new Form subclass which could be fine for many cases. E.g. override this in the state machine:
protected Component createComponentInstance(String componentType, Class cls) {
if(cls == From.class) {
return new MyForm();
}
return super.createComponentInstance(componentType, cls);
}
Notice that we are in the process of moving to a new more traditional GUI builder, right now its in technology preview state (translation: buggy as hell and lots of missing features) but this should be trivial in the future. See:
https://www.codenameone.com/blog/new-gui-builder.html
https://www.codenameone.com/blog/gui-builder-walkthru.html
https://www.codenameone.com/blog/terse-syntax-migration-wizard-more.html

Drupal: D7 rewriting values returned by views

I have a requirement to perform an indexed search across content which must include a couple of tags in the result. The tags must be a random selection. The platform is Drupal 7.12
I have created a view that manages the results of a SOLR search through the search_api. The view returns the required content and seems to work as intended. I have included a couple of Global: custom text fields as placeholders for the tag entries.
I am now looking for a solution to manage the requirement to randomise the tag values. The randomisation is not the issue, the issue is how to include the random values into the view result.
My current approach is to write a views_pre_render hook to intercept the placeholders which appear as fields ([nothing] and [nothing_1]). The test code looks like the following
function MODULE_views_pre_render( &$view )
{
$view_display = $view->display['default'];
$display_option = $view_display->display_options;
$fields = $display_option['fields'];
foreach( $view->result as $result )
{
$fields['nothing']['alter']['text'] = sprintf("test %d", rand(1,9));
}
}
I am currently not seeing any change in the placeholder when the view is rendered.
Any pointers to approach, alternate solutions etc would be gratefully received as this is consuming a lot of scarce time at the moment. Calling print_r( $view ) from within the hook dumps over 46M into a log file for a result set of 2 items.
There are two possible solutions for your task.
First approach is do everything on the template level. Define a template for the view field you want to randomize. In advanced settings of your display go to Theme: Information. Make sure that the proper theme is selected and find the template suggestions for your field. They are listed starting from most general to the most specific and you can choose whatever suits you better.
I guess the most specific template suggestion for your field would be something like this: views-view-field--[YOR VIEW NAME]--[YOUR DISPLAY NAME]--nothing.tpl.php. Create the file with that name in the theme templates directory and in this template you can render what ever you want.
By default this template has only one line:
print $output;
you can change this to:
print sprintf("test %d", rand(1,9));
or to anything else, whatsoever :)
Second approach is to go with Views PHP module. WIth this module you can add a custom PHP field in which you can do whatever you want. Even though the module hasn't been released it seems to work quite well for the most of the tasks and most certainly for such a simple task as randomizing numbers it will work out for sure.
I stumbled upon this while searching for another issue and thought I would contribute.
Instead of adding another module or modifying a template, just add a views "sort criteria" of "Global: Random".

Change Default Winform Icon Across Entire App

Can I change the default icon used on a Winform?
Most of my forms have their icon property set to a custom icon. For the few forms that slip through the cracks, I don't want the generic "hey look, he made this in visual studio" icon.
One solution is to tediously check every one of my forms to make sure they either have a custom icon set or have ShowIcon set to False.
Another solution is to have every one of my forms inherit from a base class that sets a custom icon in the constructor.
Aside from those solutions, what other options do I have?
EDIT:
I was hoping there would be a way to replace the source of the stock icon with my own. Is it in a resource file somewhere? Or is it embedded in a .NET dll that I can't (or really, really shouldn't) modify?
BOUNTY EDIT:
Is there a way to accomplish this without editing or writing a single line of code? I don't care how impractical, complicated, waste-of-time the solution is... I just want to know if it's possible. I need to satisfy my curiosity.
The default icon is embedded in the winforms dll - looking at reflector (DefaultIcon) it is:
defaultIcon = new Icon(typeof(Form), "wfc.ico");
There is no magic in there that checks another common location, so you can't do it without changing code.
You could always embrace the forces of darkness with field-based reflection? Note: this is hacky and brittle. On your own head! But it works:
[STAThread]
static void Main() {
// pure evil
typeof(Form).GetField("defaultIcon",
BindingFlags.NonPublic | BindingFlags.Static)
.SetValue(null, SystemIcons.Shield);
// all forms now default to a shield
using (Form form = new Form()) {
Application.Run(form);
}
}
To do it properly; two common options;
a base Form class which has the icon set
a factory Form method - perhaps something like:
code:
public static T CreateForm<T>() where T : Form, new() {
T frm = new T();
frm.Icon = ...
// any other common code
return frm;
}
Then instead of:
using(var frm = new MySpecificForm()) {
// common init code
}
Something like:
using(var frm = Utils.CreateForm<MySpecificForm>()) {
}
Of course - that isn't much prettier! Another option might be a C# 3.0 extension method, perhaps as a fluent API:
public static T CommonInit<T>(this T form) where T : Form {
if(form != null) {
form.Icon = ...
//etc
}
return form;
}
and
using(var frm = new MySpecificForm().CommonInit()) {
// ready to use
}
This is then just a .CommonInit() away from your existing code.
The base class option is the one that we use.
If you are looking for an alternative (not necessarily good ones), you could:
1. Use IOC to instantiate all of your forms and modify the IOC container to set the application icon.
2. Use AOP to insert code into all of the forms that sets the application icon.
Personally, I'd just use the base class...
My useful answer:
No
Would be a nice feature for microsoft to implement though, since most apps use the same icon across the entire application.
If you want to update all the icons by another one, you can build a small app that edits all the *.Designer.vb files (in vb.net) and adding the folowing line to InitializeComponent:
Me.Icon = New System.Drawing.Icon("C:\PathTo\icon.ico")
Hope it helps.
If all your forms are in just one project then you can take the dll of the project and use reflection to get every type in the dll. If the type derives from Form you can set the type's Icon property to whatever you want. I am not sure what the performance overhead will be if the project is very big.

Dynamic Hyperlink in Livecycle Form

I am trying to figure out how to make a hyperlink in a Livecycle Form which points to a URL which will change on different days that the form is rendered. For example on one day I might want the hyperlink to point to:
mywebsite/mypage?option=XXX
and on another day I want it to point to:
mywebsite/mypage?option=YYY
The XXX and YYY can be passed into the form's data pretty easily as XML, but I just don't know how to make it so that the hyperlink is changed to correspond to this.
Any suggestions?
This can be accomplished with JavaScript in LiveCycle Designer. The following script, placed on the Form's docReady event will let you dynamically change the URL of a text object.
form1::docReady - (JavaScript, client)
// If this code is running on the server, you don't want it to run any code
// that might force a relayout, or you could get stuck in an infinite loop
if (xfa.host.name != "XFAPresentationAgent") {
// You would load the URL that you want into this variable, based on
// whatever XML data is being passed into your form
var sURL = "www.stackoverflow.com"; // mywebsite/mypage?option=xxx
// URLs are encoded in XHTML. In order to change the URL, you need
// to create the right XHTML string and push it into the Text object's
// <value> node. This is a super simple XHTML shell for this purpose.
// You could add all sorts of markup to make your hyperlink look pretty
var sRichText = "<body><p>Foo</p></body>";
// Assuming you have a text object called "Text1" on the form, this
// call will push the rich text into the node. Note that this call
// will force a re-layout of the form
this.resolveNode("Text1").value.exData.loadXML(sRichText, false, true);
}
There are a couple of caveats: URLs in Acrobat are only supported in Acrobat 9.0 and later. So if someone using an older version of Acrobat opens your form, the URLs won't work.
Also, as you can see from the "if (xfa.host.name !=...)" line, this code won't run properly if the form is being generated on the server, because forcing a re-layout of a form during docReady can cause problems on certain older versions of the LiveCycle server. If you do need to run this script on the server, you should probably pick a different event then form::docReady.
I a number of complaints from users in WorkSpace that clicking links opened them in the same tab so they lost their WorkSpace form, and there's no option to change that in Designer 11. I think the solution I came up with for that would work for you too.
I made buttons with no border and no background, and in their click event have this line (in Javascript, run at client)
app.launchURL("http:/stackoverflow.com/", true);
It would be easy to add some logic to choose the right URL based on the day and it doesn't cause any form re-rendering.
In some spots where the hyperlink is in line with other text, I leave the text of the link blue and underlined but with no hyperlink, and just place the button (no background, no border, no caption) over it. Does require positioned and not flowed subforms for that to work, so depending on your layout it could get a little clunky.
Wow, just realized I am super late to the party. Well, for anyone using ES4 facing a similar problem . . .
Ended up using a 3rd party component to manipulate the PDF's hyperlinks...wish there was a better solution as this one costs about $1000.

Resources