I have a Page which consist of AddPage.xaml and AddPage.xaml.cs. I want to create a generic class AddPage which extends from PhoneApplicationPage to outsource some repetitive code like Save or Cancel.
If I change the base class from PhoneApplicationPage to my new generic class, I get this error: Partial declarations of 'AddPage' must not specify different base classes.
To accomplish this you need to do the following.
First, create your base class
public class SaveCancelPhoneApplicationPage : PhoneApplicationPage
{
protected void Save() { ... }
protected void Cancel() { ... }
}
Then, your AddPage needs to be modified to inherit from the base class. The main places this is needed is within the code (AddPage.xaml.cs) AND within the xaml
Code:
public partial class AddPage : SaveCancelPhoneApplicationPage { ... }
Xaml:
<local:SaveCancelPhoneApplicationPage
x:Class="MyPhone.Namespace.AddPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyPhone.Namespace"
<!-- other xaml elements -->
</local:SaveCancelPhoneApplicationPage>
UPDATE: Info added based on comments
If you need to have generic like functionality and you must use the Page to do this (rather than a ViewModel) then you can still do this using generic methods
public abstract class SaveCancelPhoneApplicationPage : PhoneApplicationPage
{
protected override void OnNavigatedTo(blaa,blaa)
{
var obj = CreateMyObject();
obj.DoStuff();
}
// You should know what your objects are,
// don't make it usable by every phone dev out there
protected MyBaseObject MyObject { get; set; }
protected T GetMyObject<T>() where T : MyBaseObject
{
return MyObject as T;
}
}
public class AddPage : SaveCancelPhoneApplicationPage
{
public AddPage()
{
MyObject = new MyAddObject();
}
}
In order to outsource some functions you just declare some add class which does the common work. Having another page doesn't do that work.
public class Add
{
public bool SaveContent(string filename, string content)
{
....//some content
return true;
}
public string ViewContent(string filename)
{
string content="";
.....
return content;
}
}
Add this part of code where you thought it is redundant.
Add obj=new Add();
obj.SaveContent("myfile.txt","Hello.This is my content.");
string content("myfile.txt");
Tell me if this is what you intend or not.
Related
In Visual Studio when you select project or project items in the solution explorer there are times when you might want to add custom properties to the properties window(the window that pops up when you press F4). Also, to fill in the values of those properties I need to add a button to pop up a form so I can collect information from the user at design time.
What is the simplest implementation of this so I can get started?
How would I create a user interface to collect the value some how by using UITypeEditAttribute?
This is the simplest implementation I could come up with.
Since this is an advanced topic, it is implied that you feel comfortable with completing all the steps before you start the implementation(these are all common programming tasks).
If anything is not clear enough just comment and I will try to simplify. Note that this is configured to create a custom property for a Visual C# file within visual studio. When you run or debug your visual studio package followed by clicking any .cs file, the custom property should show in the properties window. The comments provided are required instructions.
Create a Visual Studio package.
Create an interface that implements the custom properties that you would like to add to the properties page.
Create a class that implements the custom property interface and decorate the custom property with attributes.
Create class that implements IExtenderProvider interface and override GetExtender and CanExtend methods.
Create a new class that inherits from UITypeEditor and override GetEditStyle and EditValue methods.
Let's get started.
1. Create Package in visual studio.
Package.cs
// ...
public sealed class ThePackage : Package
{
private DTE2 Host;
private ObjectExtenders _extensionManager;
private MyExtenderProvider _extenderProvider;
protected override void Initialize()
{
Host = (DTE2)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SDTE));
_extenderProvider = new MyExtenderProvider();
_extenderProviderCookie = Host.ObjectExtenders.RegisterExtenderProvider(VSConstants.CATID.CSharpFileProperties_string,
"MyExtenderProvider", _extenderProvider);
}
protected override void Dispose(bool disposing)
{
Host.ObjectExtenders.UnregisterExtenderProvider(_extenderProviderCookie);
_extenderProvider = null;
base.Dispose(disposing);
}
}
2. Create class that implements your desired custom properties.
[ComVisible(true)] // Important!
public interface IMyDynamicExtender
{
String NewProperty { get; set; }
}
3. Create a class that implements the custom property interface.
[ComVisible(true)] // Important!
public class NewPropertyExtender : IMyDynamicExtender, IDisposable
{
// These attibutes supply the property with some information
// on how to display and which UITypeEditor to use.
[DisplayName("New Property")]
[Category("New")]
[Description("Specifies the new property")]
[Editor(typeof(CustomUiTypeEditor), typeof(UITypeEditor))]
public String NewProperty { get; set; }
private readonly IExtenderSite _extenderSite;
private readonly int _cookie;
private bool _disposed;
public NewPropertyExtender(IExtenderSite extenderSite, int cookie)
{
_extenderSite = extenderSite;
_cookie = cookie;
}
public void Dispose()
{
Dispose(true);
// take the instance off of the finalization queue.
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing && _cookie != 0)
{
_extenderSite.NotifyDelete(_cookie);
}
_disposed = true;
}
}
4. Create class that implements [IExtenderProvider] interface and override [GetExtender] and [CanExtend] methods.
public class MyExtenderProvider : IExtenderProvider
{
private IMyDynamicExtender _extender;
public object GetExtender(string extenderCatid, string extenderName,
object extendeeObject, IExtenderSite extenderSite,
int cookie)
{
return _extender = CanExtend(extenderCatid, extenderName, extendeeObject) ?
new NewPropertyExtender(extenderSite, cookie) : null;
}
public bool CanExtend(string extenderCatid, string extenderName, object extendeeObject)
{
// Some implementation will be here in the real world.
return true;
}
}
5. Create a new class that inherits from [UITypeEditor] and override [GetEditStyle] and [EditValue] methods.
public class CustomUiTypeEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
// Use the result of a dialog or something else here.
return "HELLO WORLD";
}
}
I have a SiteNavigation class that is being updated in the Initialize event of my base controller e.g.
[Serializable]
public class SiteNavigation
{
public SiteNavigation()
{
IsSummarySelected = true;
}
public Model.Dtos.Folder[] Folders { get; set; }
public bool IsSummarySelected { get; set; }
}
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
var siteNavigation = new SiteNavigation();
siteNavigation.Folders = GetMeMyFolders() as Folder[];
ViewBag.SiteNavigation = siteNavigation;
}
and in the controller the IsSummarySelected property is changed to this value.
ViewBag.SiteNavigation.IsSummarySelected = false;
When I access the property in the _Layout file with this line of code, the value is ALWAYS true. It's as if the nav object is being New'd up again and the constructor is setting it to true.
#if (ViewBag.SiteNavigation.IsSummarySelected)
I've tried casting the nav object back to a variable and setting the property that way too, no dice. Any help would be appreciated.
Call me baffled!
Thank you,
Stephen
I just copy pasted your code into my sample mvc project, and changing IsSummarySelected in my action correctly was reflected in the _Layout file. Are you certain your controller's assignment is getting hit, and you're not reassigning it afterwards somewhere else?
Edit: Your issues are an example of why I think it's a bad idea to use ViewBag for anything other than a localized quick fix. Debugging dynamic global objects is no fun. Refactoring suggestion: Make a site Navigation property in your base controller
SiteNavigation siteNavigation;
public SiteNavigation SiteNavigation
{
get
{
return siteNavigation;
}
set
{
siteNavigation = value;
}
}
and replace all references to ViewBag.SiteNavigation with this. Then create a custom WebViewPage and put in it.
public SiteNavigation SiteNavigation
{
get
{
return ((BaseController)ViewContext.Controller).SiteNavigation;
}
}
This won't fix your problem, but now you can just stick breakpoints on the get and set properties of SiteNavigation, and it should be very easy to debug your issue now.
I fill my TempData["SplitterIsCollapsed"] when Filters are invoked then via OnResultExecuting method. Additionally i fetch a property state from my UserContext class, which is registered only once per session: builder.RegisterType().As().CacheInSession(); .
Basic info: I use DependcyInjection!
Assignment of the Filter to the Controller:
Controller:
[LayoutTempData]
public class HomeController : Controller
{
//....
}
FilterAttribute class:
namespace MyProject.Web.Infrastructure.Filters
{
public class LayoutTempDataAttribute : ActionFilterAttribute
{
private readonly IUserContext _userContext;
public LayoutTempDataAttribute()
{
_userContext = DependencyResolver.Current.GetService<IUserContext>();
}
public override void OnResultExecuting(ResultExecutingContext context)
{
if (context.Controller.TempData.ContainsKey("SplitterIsCollapsed"))
context.Controller.TempData["SplitterIsCollapsed"] = _userContext.LayoutInformation.SplitterIsCollapsed;
else
context.Controller.TempData.Add("SplitterIsCollapsed", _userContext.LayoutInformation.SplitterIsCollapsed);
}
}
}
The Splitter part of the _Layout.cshtml looks like:
#{Html.Telerik().Splitter().Name("Splitter1")
.Panes(panes =>
{
panes.Add()
.Size("300px")
.Collapsible(true)
.Collapsed((bool)TempData["SplitterIsCollapsed"])
.Content(<div>asdfasdf</div>);
panes.Add()
.Collapsible(false)
.Scrollable(false)
.Content(<div>content2</div>);
})
.Render();
}
I am using Ninject and the MVC3 extension installed with nuget. My kernel setup code is in the App_Start/NinjectMVC3.cs file. Everything works great in controllers, but I can't figure out how to (properly) bind interfaces in the Global.asax.cs MvcApplication code.
I ended up using a hack (creating a public NinjectMVC3.GetKernel() method that returns bootstrap.kernel). However, that will be deprecated, and there must be a proper way to do this that I am not seeing.
Here is my code:
public class LogFilterAttribute : ActionFilterAttribute
{
private IReportingService ReportingService { get; set; }
public LogFilterAttribute( IReportingService reportingService )
{
this.ReportingService = reportingService;
}
...
}
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters( GlobalFilterCollection filters )
{
filters.Add( new HandleErrorAttribute() );
filters.Add( new LogFilterAttribute() );
}
...
protected void Application_Start()
{
...
RegisterGlobalFilters( GlobalFilters.Filters );
// NOTE hack:
var kernel = NinjectMVC3.GetKernel();
var logger = kernel.Get<ILogger>();
var bw = new BackgroundWork(logger);
Application["BackgroundWork"] = bw;
bw.Start();
}
}
There are two interfaces I am interested in. The first is just binding an object to a Global variable (the ILogger for the BackgroundWork).
And the second is for an ActionFilter. I read http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/, but I don't see how it plugs into the actual registration (filter.Add).
I don't want to use the Property Inject if I can avoid it.
Any thoughts on the proper way to do this?
Thanks
MVC 3 introduces the DependencyResolver which is populated into a singleton, and the Ninject extension supports it. You could use that in your MvcApplication class if you need it:
protected void Application_Start()
{
// ...
var logger = DependencyResolver.Current.GetService<ILogger>();
}
Now I should point out that it is unnecessary to do this with action filters. In Ninject.MVC3 you are supposed to use the BindFilter syntax, like so:
// Declare empty attribute
public class MyFilterAttribute : FilterAttribute { }
// Dependency module
public class MyModule : NinjectModule
{
public override void Load()
{
// Other bindings
// ...
this.BindFilter<MyActionFilter>(FilterScope.Action, 1)
.WhenControllerHas<MyFilterAttribute>();
}
}
Note that you have to use this because BindFilter is an extension method, and you also have to reference the Ninject.Web.Mvc.FilterBindingSyntax namespace.
New to the world of TDD and I have soon find out that mocking at times is not as easy.
We are using MOQ at work so I need to learn how to do this using moq
I have some code using the command pattern and works a treat.However If were to test drive it I would not know how to do it implementing the code below.
I have done the following
Created BaseToolStripMenuItem:ToolStripMenuItem and added a Command Property (see below)
Created a windows form and added a menuStrip with 2 item Open and Exit
In the form I just add to map the command to a button and all works a treat.
I would like to change the code so that I can UnitTest using Moq but cannot see how???
Can you help?
Any suggestions?
Thanks a lot!!
public interface ICommand
{
void Execute()
}
public abstract class BaseCmd :ICommand
{
protected ProcessMenuCommand ProcessCommand;
protected MenuCommandFactory Factory;
protected BaseCmd(ProcessMenuCommand processMenuCommand, MenuCommandFactory cmdfactory)
{
ProcessCommand = processMenuCommand;
Factory = cmdfactory;
}
abstract public void Execute();
}
public class BaseToolStripMenuItem : ToolStripMenuItem
{
public BaseToolStripMenuItem()
{
Click += MenuItemClick;
Command = null;
}
public BaseCmd Command { get; set; }
private void MenuItemClick(object sender, EventArgs args)
{
if (Command != null) Command.Execute();
}
}
public class MenuCommandFactory
{
private readonly ProcessMenuCommand _processMenuCommand;
public MenuCommandFactory(ProcessMenuCommand processMenuCommand)
{
_processMenuCommand = processMenuCommand;
}
public OpenFileCmd OpenFile()
{
return new OpenFileCmd(_processMenuCommand,this);
}
public ExitCmd Exit()
{
return new ExitCmd(_processMenuCommand, this);
}
}
public class OpenFileCmd:BaseCmd
{
public OpenFileCmd(ProcessMenuCommand processMenu,MenuCommandFactory menuCommandFactory)
:base(processMenu,menuCommandFactory)
{
}
public override void Execute()
{
ProcessCommand.OpenFile();
}
}
public class ProcessMenuCommand
{
public void OpenFile()
{
MessageBox.Show("Open a file");
}
public void Exit()
{
MessageBox.Show("Exiting");
}
}
public class ExitCmd:BaseCmd
{
public ExitCmd(ProcessMenuCommand processMenu, MenuCommandFactory menuCommandFactory)
:base(processMenu,menuCommandFactory)
{
}
public override void Execute()
{
ProcessCommand.Exit();
}
}
//In the form
public partial class Form1 : Form
{
private ProcessMenuCommand menuCommandProcessor;
private MenuCommandFactory factory;
public Form1()
{
InitializeComponent();
// Created editor and factory.
menuCommandProcessor = new ProcessMenuCommand();
factory = new MenuCommandFactory(menuCommandProcessor);
// Get concrete command objects from factory and assign to corresponding menu items and tool strip buttons.
tsOpen.Command = factory.OpenFile();
tsExit.Command = factory.Exit();
}
}
However If were to test drive it I would not know how to do it implementing the code below
The idea about TDD is that it drives you towards an implementation. There are many implementations you could never arrive at using TDD, so your question doesn't really make much sense.
Try to write some tests that drive you towards your goal without having a preconceived image of the solution at which you wish to arrive. It will often turn out that you end up at an entirely different (and better) place than what you originally thought.
A simple Novice Rule: no abstract classes. Try designing again with only interfaces and concrete classes. You'll notice it's easier to test-drive the result.
As for "how to TDD a Command object", a Command is just a class that provides a single action. Test-drive it the same way you would test-drive any method, except you name the method Execute().
I've got a server control that contains nested server controls,
<uc1:ArticleControl runat="server">
<HeadLine></HeadLine>
<Blurb></Blurb>
<Body></Body>
</uc1:ArticleControl>
Code:
[ToolboxData("<{0}:ArticleControl runat=server></{0}:ArticleControl>")]
[ParseChildren(ChildrenAsProperties = true)]
public class ArticleControl : WebControl
{
[PersistenceMode(PersistenceMode.InnerProperty)]
public HeadLineControl HeadLine
{
get;
set;
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public BlurbControl Blurb
{
get;
set;
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public BodyControl Body
{
get;
set;
}
}
Nested control definition (applies to all nested controls):
public class HeadLineControl : ControlBase
{
public HeadLineControl() : base() { }
public HeadLineControl(Article article) : base(article) { }
Base class definition
public abstract class ControlBase : Control
{
protected Article article;
protected ControlBase() { }
protected ControlBase(Article article)
{
this.article = article;
}
The ArticleControl is responsible for writing for the individual parts of the article specified by the nested controls,
My problem is that when the Articlecontrol is created, instances of the nested server controls are created by the .NET framework using the default constructor defined for the System.Web.Ui.Control class eg:
namespace System.Web.UI
{
public class Control : IComponent, IDisposable, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor
{
// Summary:
// Initializes a new instance of the System.Web.UI.Control class.
public Control();
I need to call or override the default behaviour of .Net to call my Control base class constructor in stead of the default .Net defined contructor. So in short, if a new instance of HeadLineControl is created, it needs to created by the ControlBase(Article article) constuctor.
Is this possible and if possible, how do I accomplish this?
I've done this in the meanwhile as a workaround, but there must be a better way?
[PersistenceMode(PersistenceMode.InnerProperty)]
public HeadLineControl HeadLine
{
get { return null; }
set
{
this.Controls.Add(new HeadLineControl(articlePage.Article)();
}
}