WebBrowser Control - Console Application - Events Not Firing - printing

I have been navigating the various WebBrowser control stackoverflow questions, and I can't seem to find an answer to a problem I am having. I am trying to use the WebBrowser control to print a web page. Following MSDN's example, I have created the following console application:
namespace WebPrintingMadness
{
using System;
using System.Collections.Generic;
using System.Text;
/// <summary>
/// The entry point of the program.
/// </summary>
class Program
{
/// <summary>
/// The main entry point of the program.
/// </summary>
/// <param name="args">Program arguments.</param>
[STAThread]
public static void Main(string[] args)
{
string url = "https://stackoverflow.com/";
WebPagePrinter webPagePrinter = new WebPagePrinter();
webPagePrinter.PrintWebPage(url);
Console.ReadLine();
}
}
}
namespace WebPrintingMadness
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
/// <summary>
/// This class is used to print a web page.
/// </summary>
internal class WebPagePrinter : IDisposable
{
/// <summary>
/// A System.Windows.Forms.WebBrowser control.
/// </summary>
private WebBrowser webBrowser;
/// <summary>
/// Initializes a new instance of the WebPagePrinter class.
/// </summary>
internal WebPagePrinter()
{
this.webBrowser = new WebBrowser();
this.webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(this.WebBrowser_DocumentCompleted);
this.webBrowser.ScriptErrorsSuppressed = true;
}
/// <summary>
/// Disposes of this instance.
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Prints a web page.
/// </summary>
/// <param name="url">The url of the web page.</param>
internal void PrintWebPage(string url)
{
this.webBrowser.Navigate(url);
}
/// <summary>
/// Disposes of this instance.
/// </summary>
/// <param name="disposing">True if disposing, otherwise false.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (this.webBrowser != null)
{
this.webBrowser.Dispose();
this.webBrowser = null;
}
}
}
/// <summary>
/// Event handler for the webBrowser DocumentCompleted event.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event arguments.</param>
private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser navigated = sender as WebBrowser;
if (navigated == null)
{
return;
}
navigated.Print();
navigated.Dispose();
}
}
}
However, the DocumentCompleted event never fires. Is it possible to use this Windows.Forms control in an console application?

It will work as long as process events while it's running.
You can simply call "Application.DoEvents()" in a wait loop. You don't need to do anything fancier than that, and it works fine in my console application.

The basic requirement of an STA thread is that it needs to run a message pump.
In Windows Forms, you can use Application.Run. Or you could write the message pump by hand, using user32!GetMessage & DispatchMessage. But it's probably easier to use the one in WinForms or WPF.

Related

Register all modules exported using MEF and autofac

Using the Autofac.Mef extension I want to register exported Modules. Is there a way?
Exporting
[Export(typeof(IModule))]
public class MyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<SampleJob>().AsSelf();
}
}
Registering
var catalog = new DirectoryCatalog(".");
builder.RegisterComposablePartCatalog(catalog); //This would register all exported types.
builder.RegisterModule(//All IModules registerd as that type I want to register as Modules)
There is a very good writeup about one such approach in Unleashing modules – part 2. The approach is to use a delegate as a factory to create the modules instead of exporting the IModule type.
using Autofac;
/// <summary>
/// Creates an <see cref="IModule" /> that's responsible for loading
/// dependencies in the specified context.
/// </summary>
/// <param name="mode">The mode the application is running in, let's the implementor
/// of the factory load different dependenices for different modes.</param>
/// <returns>An <see cref="IModule" />.</returns>
public delegate IModule ModuleFactory(ApplicationMode mode);
/// <summary>
/// Describes different modes an application can run in.
/// </summary>
public enum ApplicationMode
{
/// <summary>
/// The application is running in a test environment.
/// </summary>
Test = 0,
/// <summary>
/// The application is running in a staging environment.
/// </summary>
Staging = 1,
/// <summary>
/// The application is running in production environment.
/// </summary>
Production = 2
}
The real magic happens in the ComposedModule.
using Autofac.Builder;
using Autofac;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Collections.Generic;
using System;
/// <summary>
/// An <see cref="Autofac.Builder.Module" /> is composed by with the help of
/// the System.ComponentModel.Composition (MEF) framework.
/// </summary>
public class ComposedModule
: global::Autofac.Builder.Module
{
#region Fields
private ApplicationMode mode;
private ComposablePartCatalog catalog;
[Import(typeof(ModuleFactory))]
private IEnumerable<ModuleFactory> RegisteredModuleFactories;
#endregion
#region Construction
/// <summary>
/// Creates a new ComposedModule using the specified catalog to
/// import ModuleFactory-instances.
/// </summary>
/// <param name="mode">The mode the application is running in.</param>
/// <param name="catalog">The catalog used to import ModuleFactory-instances.</param>
public ComposedModule(ApplicationMode mode, ComposablePartCatalog catalog)
{
if (catalog == null) throw new ArgumentNullException("catalog");
this.mode = mode;
this.catalog = catalog;
this.ImportFactories();
}
/// <summary>
/// Creates a new ComposedModule that loads all the ModuleFactories
/// exported in assemblies that exists in the directory specified in
/// the <param name="modulesDirectoryPath" />-parameter.
/// </summary>
/// <param name="mode">The mode the application is running in.</param>
/// <param name="catalog">The catalog used to import ModuleFactory-instances.</param>
public ComposedModule(ApplicationMode mode, string modulesDirectoryPath)
: this(mode, new DirectoryCatalog(modulesDirectoryPath)) { }
#endregion
#region Methods
private void ImportFactories()
{
var batch = new CompositionBatch();
batch.AddPart(this);
var container = new CompositionContainer(this.catalog);
container.Compose(batch);
}
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
foreach (var factory in this.RegisteredModuleFactories)
{
var module = factory(this.mode);
builder.RegisterModule(module);
}
}
#endregion
}
Usage
public class MyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterType<SampleJob>().AsSelf();
}
[Export(typeof(ModuleFactory))]
public static ModuleFactory Factory = x => new MyModule();
}
See the post for complete details.
Also, you might want to check out these links:
http://buksbaum.us/2009/12/06/bootstrapping-an-application-with-mef-and-autofac/
http://kalcik.net/2014/02/09/cooperation-between-the-autofac-and-the-microsoft-extensibility-framework/

Converting from a repository factory to an IOC solutions for EF?

I have an application which borrows a lot of code from the John Papa Code Camper application. In his applicatione he uses a Repository factory to provide a new repository or an existing repository if one already exists in cache. To me this seems overly complicated and I am wondering if I could use Unity to do the same thing. Here's an example of the code that I am currently using:
In the UOW he has this code to get the repos:
public IRepository<Answer> Answers { get { return GetStandardRepo<Answer>(); } }
This code to call the repository provider:
protected IRepositoryProvider RepositoryProvider { get; set; }
protected IRepository<T> GetStandardRepo<T>() where T : class
{
return RepositoryProvider.GetRepositoryForEntityType<T>();
}
protected T GetRepo<T>() where T : class
{
return RepositoryProvider.GetRepository<T>();
}
The following respository provider:
public class RepositoryProvider : IRepositoryProvider
{
public RepositoryProvider(RepositoryFactories repositoryFactories)
{
_repositoryFactories = repositoryFactories;
Repositories = new Dictionary<Type, object>();
}
//public RepositoryProvider(RepositoryFactories repositoryFactories)
//{
// _repositoryFactories = repositoryFactories;
// Repositories = new Dictionary<Type, object>();
//}
/// <summary>
/// Get and set the <see cref="DbContext"/> with which to initialize a repository
/// if one must be created.
/// </summary>
public DbContext DbContext { get; set; }
/// <summary>
/// Get or create-and-cache the default <see cref="IRepository{T}"/> for an entity of type T.
/// </summary>
/// <typeparam name="T">
/// Root entity type of the <see cref="IRepository{T}"/>.
/// </typeparam>
/// <remarks>
/// If can't find repository in cache, use a factory to create one.
/// </remarks>
public IRepository<T> GetRepositoryForEntityType<T>() where T : class
{
return GetRepository<IRepository<T>>(
_repositoryFactories.GetRepositoryFactoryForEntityType<T>());
}
/// <summary>
/// Get or create-and-cache a repository of type T.
/// </summary>
/// <typeparam name="T">
/// Type of the repository, typically a custom repository interface.
/// </typeparam>
/// <param name="factory">
/// An optional repository creation function that takes a DbContext argument
/// and returns a repository of T. Used if the repository must be created and
/// caller wants to specify the specific factory to use rather than one
/// of the injected <see cref="RepositoryFactories"/>.
/// </param>
/// <remarks>
/// Looks for the requested repository in its cache, returning if found.
/// If not found, tries to make one using <see cref="MakeRepository{T}"/>.
/// </remarks>
public virtual T GetRepository<T>(Func<DbContext, object> factory = null) where T : class
{
// Look for T dictionary cache under typeof(T).
object repoObj;
Repositories.TryGetValue(typeof(T), out repoObj);
if (repoObj != null)
{
return (T)repoObj;
}
// Not found or null; make one, add to dictionary cache, and return it.
return MakeRepository<T>(factory, DbContext);
}
/// <summary>
/// Get the dictionary of repository objects, keyed by repository type.
/// </summary>
/// <remarks>
/// Caller must know how to cast the repository object to a useful type.
/// <p>This is an extension point. You can register fully made repositories here
/// and they will be used instead of the ones this provider would otherwise create.</p>
/// </remarks>
protected Dictionary<Type, object> Repositories { get; private set; }
/// <summary>Make a repository of type T.</summary>
/// <typeparam name="T">Type of repository to make.</typeparam>
/// <param name="dbContext">
/// The <see cref="DbContext"/> with which to initialize the repository.
/// </param>
/// <param name="factory">
/// Factory with <see cref="DbContext"/> argument. Used to make the repository.
/// If null, gets factory from <see cref="_repositoryFactories"/>.
/// </param>
/// <returns></returns>
protected virtual T MakeRepository<T>(Func<DbContext, object> factory, DbContext dbContext)
{
var f = factory ?? _repositoryFactories.GetRepositoryFactory<T>();
if (f == null)
{
throw new NotImplementedException("No factory for repository type, " + typeof(T).FullName);
}
var repo = (T)f(dbContext);
Repositories[typeof(T)] = repo;
return repo;
}
/// <summary>
/// Set the repository for type T that this provider should return.
/// </summary>
/// <remarks>
/// Plug in a custom repository if you don't want this provider to create one.
/// Useful in testing and when developing without a backend
/// implementation of the object returned by a repository of type T.
/// </remarks>
public void SetRepository<T>(T repository)
{
Repositories[typeof(T)] = repository;
}
/// <summary>
/// The <see cref="RepositoryFactories"/> with which to create a new repository.
/// </summary>
/// <remarks>
/// Should be initialized by constructor injection
/// </remarks>
private RepositoryFactories _repositoryFactories;
}
Is this something that I could use Unity for and if so can someone give me some hints on how I could create the repositories in Unity so that that they could be shared. Note that I have two types of repositories. A generic and a custom. Right now these are returned using GetStandardRepo and GetRepo. I would like if possible to have the mapping that decideds which repo I get inside my Unity config file so that it's clearly visible.
Here is the Unity Config I have so far:
container.RegisterType<RepositoryFactories>(new ContainerControlledLifetimeManager());
container.RegisterType<IRepositoryProvider, RepositoryProvider>();
container.RegisterType<IUow, Uow>();
container.RegisterType<Contracts.Services.IContentService, Services.ContentService>();
container.RegisterType<IAnswerService, AnswerService>();
Unity supports registering components "Per Request" in MVC projects. The first time a particular repository is served from the container it will be instantiated. Any subsequent requests for that repository during the same HTTP request will use this same repository rather than creating a new one.
You can read more about how this works using the link below. Basically, you're looking to control the lifetime scope of your objects as a singleton rather than for each dependency.
Unity Documentation on MSDN

Best practices for cache and session manager for an MVC Application

Masters,
We have implemented CacheManager and SessionManager in past applications by various ways, like by creating a SessionHelper static class and a CacheHelper static class.
Though it works fine, we lack some ability for generalization and globalization perspective.
So for new scratch development, we intend best practices for such general implementation in terms of flexibility and extensibility.
Please suggest.
You could create an interface to define the common operations used in Caching and Session management, named something like IStateManager. e.g.
/// <summary>
/// An interface to provide access to a state storage implementation
/// </summary>
public interface IStateManager
{
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>The value associated with the specified key.</returns>
T Get<T>(string key);
/// <summary>
/// Adds the specified key and object to the state manager.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
void Set(string key, object data);
/// <summary>
/// Adds the specified key and object to the state manager.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
/// <param name="cacheTime">Cache time</param>
void Set(string key, object data, int cacheTime);
/// <summary>
/// Gets a value indicating whether the value associated with the specified key is in the state manager.
/// </summary>
/// <param name="key">key</param>
/// <returns>Result</returns>
bool IsSet(string key);
/// <summary>
/// Removes the value with the specified key from the state manager.
/// </summary>
/// <param name="key">/key</param>
void Remove(string key);
/// <summary>
/// Removes items by pattern
/// </summary>
/// <param name="pattern">pattern</param>
void RemoveByPattern(string pattern);
/// <summary>
/// Clear all state manager data
/// </summary>
void Clear();
}
Then, you could create implementations of the interface to provide different functionality. E.g. an in memory implementation, that uses System.Runtime.Caching
/// <summary>
/// Represents an in memory cache
/// </summary>
public class MemoryCacheManager : IStateManager
{
public MemoryCacheManager()
{
}
protected ObjectCache Cache
{
get
{
return MemoryCache.Default;
}
}
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>The value associated with the specified key.</returns>
public T Get<T>(string key)
{
return (T)Cache[key];
}
/// <summary>
/// Adds the specified key and object to the cache with a default cache time of 30 minutes.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
public void Set(string key, object data)
{
Set(key, data, 30);
}
/// <summary>
/// Adds the specified key and object to the cache.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
/// <param name="cacheTime">Cache time</param>
public void Set(string key, object data, int cacheTime)
{
if (data == null)
return;
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
Cache.Add(new CacheItem(key, data), policy);
}
/// <summary>
/// Gets a value indicating whether the value associated with the specified key is cached
/// </summary>
/// <param name="key">key</param>
/// <returns>Result</returns>
public bool IsSet(string key)
{
return (Cache.Contains(key));
}
/// <summary>
/// Removes the value with the specified key from the cache
/// </summary>
/// <param name="key">/key</param>
public void Remove(string key)
{
Cache.Remove(key);
}
/// <summary>
/// Removes items by pattern
/// </summary>
/// <param name="pattern">pattern</param>
public void RemoveByPattern(string pattern)
{
var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
var keysToRemove = new List<String>();
foreach (var item in Cache)
if (regex.IsMatch(item.Key))
keysToRemove.Add(item.Key);
foreach (string key in keysToRemove)
{
Remove(key);
}
}
/// <summary>
/// Clear all cache data
/// </summary>
public void Clear()
{
foreach (var item in Cache)
Remove(item.Key);
}
}
You could create multiple implementations of this interface, such as a 'Memcached' implementation to provide distributed caching for your application or a 'Session' implementation to provide user session based functionality.
Then, you can use your dependency container of choice to inject the implementations into your services\controllers and wire up your application.
Try and avoid static classes which can be problematic to unit test.
Can use the filter attributes for caching and can handle session through the singleton class..
http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx
you can get some samples in the above link for the best way or approach to be followed.

Dynatree with ASP.NET MVC

Has anybody got any examples of using the Dynatree plugin with MVC? I have been wrestling with it without much progress. I have an action method which returns a JsonResult (but selects all columns in the underlying table, not sure if this is the problem) and in my initajax call , all I'm doing is calling this method.
If it's not too much trouble, I am looking for sample View and Controller action methods.
Thanks in advance for any help
You need to create an object to serialize the nodes eg.
public interface ITreeItem
{
}
/// <summary>
/// Tree Item Leaf.
/// </summary>
public class TreeItemLeaf :ITreeItem
{
/// <summary>
/// Gets the Title.
/// </summary>
public string title;
/// <summary>
/// Gets the Tooltip.
/// </summary>
public string tooltip;
/// <summary>
/// Gets the key.
/// </summary>
public string key;
/// <summary>
/// Gets the Data.
/// </summary>
public string addClass;
/// <summary>
/// Gets the Children.
/// </summary>
public IList<ITreeItem> children;
/// <summary>
/// Gets the rel attr.
/// </summary>
public string rel;
/// <summary>
/// Gets the State.
/// </summary>
public bool isFolder;
/// <summary>
/// Gets the State.
/// </summary>
public bool isLazy;
/// <summary>
/// Initializes a new instance of the <see cref="TreeItemLeaf"/> class.
/// </summary>
public TreeItemLeaf()
{
children = new List<ITreeItem>();
}
/// <summary>
/// Initializes a new instance of the <see cref="TreeItemLeaf"/> class.
/// </summary>
/// <param name="type">The type of node.</param>
/// <param name="id">The Id of the node.</param>
/// <param name="title">The Title of the node.</param>
/// <param name="tooltip">The Tooltip of the node.</param>
public TreeItemLeaf(String type, Guid id, String title, String tooltip)
{
key = id.ToString();
this.title = title;
isFolder = false;
isLazy = false;
this.tooltip = tooltip;
children = new List<ITreeItem>();
}
}
/// <summary>
/// Tree Item.
/// </summary>
public class TreeItem : TreeItemLeaf
{
/// <summary>
/// Gets the State.
/// </summary>
public new bool isFolder;
/// <summary>
/// Initializes a new instance of the <see cref="TreeItem"/> class.
/// </summary>
public TreeItem() : base()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TreeItem"/> class.
/// </summary>
/// <param name="type">The type of node.</param>
/// <param name="id">The Id of the node.</param>
/// <param name="title">The Title of the node.</param>
/// <param name="tooltip">The tooltip of the node.</param>
public TreeItem(String type, Guid id, String title, String tooltip) : base(type, id, title, tooltip)
{
isFolder = true;
isLazy = true;
}
}
Once you have this, you can return a Json(IList<ITreeItem>) which you will need to build up from your results..
If you go to the Dynatee demo http://wwwendt.de/tech/dynatree/doc/samples.html , you can use Firefox/Firebug to study the HTTP requests to see exactly what is being passed in and returned.
My tree in the view is as follows :
// --- Initialize first Dynatree -------------------------------------------
$("#tree").dynatree({
fx: { height: "toggle", duration: 500 },
selectMode: 1,
clickFolderMode: 1,
children : #Html.Raw(String.Format("{0}", ViewData["tree"]).Replace("\"children\":[],", "")),
onLazyRead: function (node) {
node.appendAjax({
url: "#Url.Action("treedata", "tree")",
type: "GET",
data: { "id": node.data.key, // Optional url arguments
"mode": "all"
},
error: function(node, XMLHttpRequest, textStatus, errorThrown) {
}
}
});
}, //.... cut short for brevity
I am embeding the initial tree state in the "children:" part. And the Ajax reading is being set up in the "onLazyRead:" part.
My Ajax call is:
public JsonResult TreeData(FormCollection form)
{
return GetTreeData(Request.QueryString["id"], Request.QueryString["uitype"]);
}
The GetTreeData() function returns Json(ITreeItem);
I would recommend you use Firefox/Firebug and its "NET" function to see what is going and coming back.
Hope that helps.
I've just found Dynatree and I'm using it on my MVC project. Here's an example of how I did it. I decided to just put the data directly in the View like the basic example.
My data is a list of cities within California, grouped by county.
My controller simply passes a view model to my View and the view model has a CitiesAvailable property:
public IEnumerable<City> CitiesAvailable { get; set; }
My list of City objects is grabbed from the database (EF4) and the actual City object is the following:
In my View I create a ul containing the list of counties and their cities (I'm using Razor but webforms should be easy enough to figure out):
<div id="tree">
<ul id="treedata" style="display: none;">
#foreach (var county in Model.CitiesAvailable.Select(c => c.County).Distinct().OrderBy(c => c))
{
<li data="icon: 'false'">#county
<ul>
#foreach (var city in Model.CitiesAvailable.Where(c => c.County == county).OrderBy(c => c.Name))
{
<li data="icon: 'false'" id="#city.Id">#city.Name</li>
}
</ul>
</li>
}
</ul>
</div>
Then in my JavaScript I use the following:
$("#tree").dynatree({
checkbox: true,
selectMode: 3,
fx: { height: "toggle", duration: 200 }
});
It works great! Here's a sample of the output with a few items checked:
Let me know if anything doesn't make sense.
Note, I use data="icon: 'false'" in my li elements because I don't want the icons.
You can simply convert the object to json string, and send it to server as text
this is the js code:
var dict = $("#tree").dynatree("getTree").toDict();
var postData = JSON.stringify(dict["children"]);
$.ajax({ type: "POST",
url: "/UpdateServer/SaveUserTree",
data: {tree:postData},
dataType: "html"
});
And this is the controller code:
[HttpPost]
public void SaveUserTree(string tree = "")
{
HttpContext.Application["UserTree"] = tree;
}
You can send this string data back to client
if (HttpContext.Application["UserTree"] != null)
ViewBag.TreeData = new HtmlString(HttpContext.Application["UserTree"].ToString());
And finally, you can initial the tree, in the View with this data:
var treeData= #(ViewBag.TreeData)
$(function(){
// --- Initialize sample trees
$("#tree").dynatree({
children: treeData
});
});

ASP.NET MVC: creating controls dynamically

This is the control builder class...
public class ControlBuilder
{
/// <summary>
/// Html Control class for controlbuilder Control .
/// </summary>
protected HTMLControl formControl;
/// <summary>
/// Html Control class for the label.
/// </summary>
private HTMLControl labelControl;
/// <summary>
/// Getting the property for the Control .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public HTMLControl Form
{
get { return formControl; }
}
/// <summary>
/// Creating a label for the Control.
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public HTMLControl Label
{
get { return labelControl; }
}
/// <summary>
/// Creating a construtor for the controlbuilder taking in Zero
/// arguments it creates a labl for the Control .
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
public ControlBuilder() { }
/// <summary>
/// A construtor for the controlbuilder which
/// creates a label for the Control .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public ControlBuilder(string labelName)
{
Label label = new Label();
label.Text = labelName;
label.Width= 200;
labelControl = new HTMLControl(label);
}
/// <summary>
/// Control build property that is used to biuld the Html
/// markup for the created Control.
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public string BuildControl()
{
this.CreateControl();
this.SetAttribute();
return this.RenderHTML();
}
/// <summary>
/// Render Html tags for the Control with label .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public string RenderHTML()
{
return labelControl.RenderHTML() + ": " + formControl.RenderHTML();
}
/// <summary>
/// Used to Set Attributes for the Control .
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
protected virtual void SetAttribute() { }
/// <summary>
/// Used to create the Control .
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
protected virtual void CreateControl() { }
/// <summary>
/// A list of all the Controls that will be created during the
/// program run .
/// </summary>
private IList<ControlBuilder> Controls = new List<ControlBuilder>();
/// <summary>
/// A property to add Control to the ControlBuilder that are created by
/// the user.
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
/// <param name="Control">Controls from the controlbuilder class</param>
public void AddControl(ControlBuilder Control)
{
Controls.Add(Control);
}
/// <summary>
/// A property to display the Controls that are created by
/// the user.
/// </summary>
/// <history>
/// [LuckyR] 13/8/2009 Created
/// </history>
public string Display()
{
string Html = string.Empty;
foreach (ControlBuilder builder in Controls)
{
Html += builder.BuildControl();
Html += "<br /><br />";
}
return Html;
}
}
}
this is how i build a control
public class TextBoxBuilder : ControlBuilder
{
/// <summary>
/// Creating a web Control textBox.
/// </summary>
private TextBox textBox;
/// <summary>
/// Creating an Id to add as an attribute .
/// </summary>
private string Id;
/// <summary>
/// Creating an Value to add as an attribute .
/// </summary>
private string Value;
/// <summary>
/// Creating a Textbox constructor which takes in LabelName and Id.
/// to create a label for the Control.
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
public TextBoxBuilder(string labelName, string id , string value): base(labelName)
{
this.Id = id;
this.textBox = new TextBox();
this.Value = value;
}
/// <summary>
/// Used to Set properties for the Control .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
protected override void SetAttribute()
{
this.textBox.ID = this.Id;
this.textBox.Text = this.Value;
}
/// <summary>
/// Used to create the Control . That is done by calling the HtmlControl class
/// which inturn renders the particular Control for us .
/// </summary>
/// <history>
/// [LuckyR] 10/8/2009 Created
/// </history>
protected override void CreateControl()
{
this.formControl = new HTMLControl(this.textBox);
}
}
}
In my home controller i did this ...
public ActionResult Create()
{
///Where i am contacting the linq to sql classs for performing ths operagtion
foreach (var control in Rep.GetData(ScreenName))
{
string Type = control.Type;
string value = null;
if (id != Guid.Empty)
{
value = DataObj.GetValue(control.TableName, control.ControlName, id);
}
switch (Type)
{
case ("TextBox"):
/// Buliding a textBox box
controlbuilder.AddControl(new TextBoxBuilder(control.Field, control.ControlName, value));
break;
case ("CheckBox"):
/// Bulidig a CheckBox .
controlbuilder.AddControl(new CheckBoxBuilder(control.Field, control.ControlName , value));
break;
case ("DatePicker"):
/// Bulidig a DatePicker .
controlbuilder.AddControl(new DatePicker(control.Field, control.ControlName, value));
break;
case ("DropDownList"):
///Building a dropdownlist.
List<string> list = DataObj.GetDropDownValues(control.Id);
controlbuilder.AddControl(new DropDownListBuilder(control.Field, control.ControlName, list,value));
break;
case ("TextArea"):
/// Building a textBox area .
controlbuilder.AddControl(new TextArea(control.Field, control.ControlName , value));
break;
default:
break;
}
}
return View(controlbuilder);
}
The view page looks like this ...
<% using (Html.BeginForm())
{%>
<fieldset>
<legend>Fields</legend>
<p>
<%= ViewData.Model.Display() %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("Back to List", "Index")%>
</div>
since i am passing my class into the view i can retrieve all the data there with .display .
There is no concept of controls in ASP.NET MVC any longer.
You have two options:
When the user clicks a button, you handle this POST request in a controller action, set some sort of flag in your view model to now show a textbox, then return the same view which in its turn will look at the flag and generate a text box if required. This will incur a complete round-trip which will be somewhat similar to the postback in WebForms.
You do it in-place with JavaScript. You intercept a click event on a button and you inject an input/textarea HTML element into your document structure.

Resources