I add an Usercontrol base class
my Base Class
public class UserControlBase : UserControl
{
protected IAppLogic app;
public MainWindow CurrentWindow{
get{
return (App.Current.MainWindow as MainWindow);
}
}
public UserControlBase()
{
var _app = IoC.Kernel.Get<IAppLogic>();
this.app = _app;
}
public void MainNavigate(Pages.PageBase p)
{
CurrentWindow.MainFrame.Content = p;
}
}
but the design does not shown
Browsing around some of the other questions, I found some of the reasons this can happen
Q1 WPF Designer “Could not create an instance of type”
Suround the code in your constructor with this:
if(!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
//code producing exception
}
The base class is of the abstract type
An exception is thrown in your constructor while loading the custom control. This goes back to 1.
Please share the stacktrace for us to help more.
Related
I have created one window and declared 2 instances of my object, then I modified them and wanted to pass to another Window. My questions are:
How would i do that ?
(I can pass simple types such as string or int trough window constructor but passing my own object giving me an error (Inconsistent Accessibility parameter order is less accessible then method))
Does it have any connection with dataContext ?
Can anybody explain to me how I can achieve that (in the simplest possible way)? What are the correct ways to do that ?
Here is part of my code (everything is in one namespace):
public partial class Main_window : Window
{
Order myOrder = new Order();
Menu menu = new Menu();
public Main_window()
{ InitializeComponent() }
private void OpenSecondWindow(object sender, RoutedEventArgs e)
{
Second_Window SecondWindow = new Second_Window();
Second.ShowDialog();
}
}
// Second Window class
public partial class Second_Window : Window
{
public Second_Window(Order someOrder)
{ InitializeComponent(); }
}
Make sure that the Order type, and any other type you intend to inject the SecondWindow with, is defined as a public class:
public class Order { ... }
A non-public type cannot be part of the signature of a public method or constructor.
A little background on my project:
I'm making a multi-form application, which consists of 1 mainform, and 6 childforms that can be called from the mainform, but only 1 childform can be active at a time. These childforms share certain parts of code, which I do not want to copy. To solve this, I have a codefile within the same namespace which holds the nessaccary code.
This codefile however, needs access to certain properties of the currently active childform.
My search has come down to using an interface to extract the needed information from the active childform.
My code is currently looking like this:
Interface:
public interface Interface1
{
TabControl tabControl_Buizen_
{
get;
}
TabPage tabPage_plus_
{
get;
}
}
Childform:
public partial class Childform : Form, Interface1
{
Interface1 dummy;
public TabControl tabControl_Buizen_
{
get { return this.tabControl_Buizen; }
}
public TabPage tabPage_plus_
{
get { return this.tabPage_plus; }
}
Methods_newTabPage methods = new Methods_newTabPage(dummy);
}
Codefile:
public class Methods_newTabPage
{
private readonly Interface1 form;
public Methods_newTabPage(Interface1 formInterface)
{
this.form = formInterface;
}
}
As you can see I'm using Methods_newTabPage methods = new Methods_newTabPage(dummy); to be able to call methods in my codefile, but the codefile requires the interface to be passed (which I filled as "dummy"). This however pops the error "A field initializer cannot reference the non-static field, method, or property Childform.dummy".
How can I let the childforms access the methods in the codefile, while also giving the codefile access to certain controls in differing childforms?
The error is easy to fix: just make dummy static.
static Interface1 dummy;
However, I don't think that will help you much. Why are you passing this dummy to Methods_newTabPage anyway? This will lead to NullReferenceExceptions inside the code file because dummy was never initialized with anything.
Don't you rather want to pass this, i.e. the current instance of Childform?
But you cannot just exchange dummy with this like so:
// Compiler error "Keyword 'this' is not available in the current context".
Methods_newTabPage methods = new Methods_newTabPage(this);
Instead you have to add a constructor that creates Methods_newTabPage:
public partial class Childform : Form, Interface1
{
private Methods_newTabPage methods;
public Childform()
{
methods = new Methods_newTabPage(this);
}
public TabControl tabControl_Buizen_ { get { return this.tabControl_Buizen; } }
public TabPage tabPage_plus_ { get { return this.tabPage_plus; } }
}
Try adding a constructor that initializes the field methods.
Also I don't see how that dummy makes sense. Instead initialize methods via methods = new Methods_newTabPage(this); in the constructor.
Problem: When I execute my code it pulls up the code correctly from the inherited base class and changes the text of the base form correctly. But as soon as I, in debugger mode in VS2013, come back into the derived class and step over the InitizlieComponent(); call everything is reverted back. When I say 'reverted back' I mean that thing go back to the way that they were in the designer for the derived form.
All help would be appreciated!
Derived Class
public partial class appSuiteMenu : App.baseForm
{
public appSuiteMenu()
: base("App Suite")
{
InitializeComponent();
}
}
Base Class
public partial class baseForm : Form
{
public baseForm() { InitializeComponent(); } //Required or designer breaks
public baseForm(string formTitle=null)
{
this.initialize(formTitle);
}
private void initialize(string formTitle)
{
base.text = formTitle + " - " + //Other objects are called from the class
}
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
}
}
}
My guess would be the second call to the "InitializeComponent()" inside the derived class.
What is does, is exactly what you said. It overrwrites everything from the base initialization.
I believe you can remove it and it'll be fine:
public appSuiteMenu()
: base("App Suite")
{
}
Read more about it in here: http://www.dotnetperls.com/initializecomponent
Edit:
Here is some tests I did with two forms. One is derived from the other. The base form hase a label. The second from adds another label. When creating a form of the derived type, tou get a form with two labels. What I did was use InitializeComponent(); in both base and derived forms.
The code:
public partial class BaseForm : Form
{
public BaseForm()
{
InitializeComponent();
label1.Text = "asdf";
}
}
...
public partial class DerivedForm : BaseForm
{
public DerivedForm()
{
InitializeComponent();
label2.Text = "asdfasfd";
}
}
What happens in execution of the code is that the base initialization happens. Then the derived initialization adds only the add functionality.
It seems pretty straightforward, but Iv'e noticed you had only one InitializeComponent(); in the code above that will actually happen.
Dave,
Your edited posted is nearly what I ended up doing to correct my problem. Since I was overriding the .Text() property of the base form, I found that I didn't even have to pass anything in the constructor. Simply setting the form text in the code, or designer, changed everything for me.
In my prism application I want to make a single shared instance of a view. When I try to navigate the first time it works fine, but when I try to second time it's not working. If I change the PartCreationPolicy from Shared to NonShared it works but it's give me a new instance. Are there any options for another way to do this?
[Export(ViewNames.AppView)]
[PartCreationPolicy(CreationPolicy.Shared)]
public partial class AppMain : UserControl
{
public AppMain()
{
InitializeComponent();
}
}
You might want to play around with Prism's KeepAlive value for your view. This value determines whether the view should be removed from the region when you navigate away from it. You have two ways of doing this:
Using the RegionMemberLifetime attribute
[RegionMemberLifetime(KeepAlive = false)]
[Export(ViewNames.AppView)]
[PartCreationPolicy(CreationPolicy.Shared)]
public partial class AppMain : UserControl
{
public AppMain()
{
InitializeComponent();
}
}
Implementing the IRegionMemberLifetime interface
[Export(ViewNames.AppView)]
[PartCreationPolicy(CreationPolicy.Shared)]
public partial class AppMain : UserControl, IRegionMemberLifetime
{
public AppMain()
{
InitializeComponent();
}
public bool KeepAlive
{
get { return false; }
}
}
You can read some more about the KeepAlive property here.
I have several UserControls that are sharing some common properties. Example:
private List<MyObject> Sample
{
get
{
return Session["MyObject"] as List<MyObject>;
}
set
{
Session["MyObject"] = value;
}
}
I want to share this to all user controls inside my project. (Not to other projects in a solution, of course). What I'm trying to do is create a separate class and inherit from that class. Something like:
public class SampleBase : Web.UI.UserControl
{
protected List<MyObject> Sample
{
get
{
return Session["MyObject"] as List<MyObject>;
}
set
{
Session["MyObject"] = value;
}
}
}
And then my control can inherit those values by deriving from that class:
partial class myControl : SampleBase
One problem I encounter is that I cannot derive from base if control already has something inherited:
partial class myControl : SomethingELSE
Otherwise it works fine, but I'm not sure if it is a good approach and I'm looking for suggestions.
If my understanding is correct, you only want to get rid of the inheritance hierarchy of your User Controls
Another approach would be using Extension Methods
For example:
Interface to mark your USerControls
public interface IMyUserControlMark { }
Extensions
public static class MyUserClassExtensions
{
public static List<object> GetSampleData(this IMyUserControlMark myUserControl)
{
if (HttpContext.Current.Session["MyObject"] == null)
{
return Enumerable.Empty<object>().ToList();
}
return HttpContext.Current.Session["MyObject"] as List<object>;
}
public static void SetSampleData(this IMyUserControlMark myUserControl, List<object> myObject)
{
HttpContext.Current.Session["MyObject"] = myObject;
}
}
User control
public partial class Content1 : System.Web.UI.UserControl, IMyUserControlMark
{
...
}
public partial class Content2 : System.Web.UI.UserControl, IMyUserControlMark
{
....
}
Now you will be able to call your extension methods from within your UserControl or from the ASPX code behind like this:
From the UserControl
var myObject = this.GetSampleData();
this.SetSampleData(myObject);
From the ASPX code behind
var myObject = this.uc1.GetSampleData();
this.uc1.SetSampleData(myObject);
This is a classic example where you need to "favor composition over inheritance".
Instead of inheriting from the class, you hold a reference to an instance of the class. Then you provide simple pass-through code to access the methods/properties of the class.
So, for your example:
public class SomeBehavior
{
public List<MyObject> Sample
{
get { return Session["MyObject"] as List<MyObject>; }
set { Session["MyObject"] = value; }
}
}
public class MyControl : UserControl
{
private SomeBehavior _someBehavior;
public MyControl()
{
_someBehavior = new SomeBehavior();
}
public List<MyObject> Sample
{
get { return _someBehavior.Sample; }
set { _someBehavior.Sample = value; }
}
}
Another option is to allow access to the behavior class directly:
public class MyControl : UserControl
{
public SomeBehavior SomeBehavior { get; private set; }
public MyControl()
{
SomeBehavior = new SomeBehavior();
}
}
The advantage of this is that you don't have to write the pass-through code. The disadvantage is that it violates the Law of Demeter, which says that you should "only talk to your immediate friends". If you do it this way, other classes that use MyControl need to know about SomeBehavior. Following the Law Of Demeter can improve maintainability and adaptability of your code, but it comes at a cost of lots of pass-through code.
Apart from previous solutions, maybe it's time for applying some MVC/MVP pattern?
For web forms there is a great framework called WebFormsMVP: link
In the library there is a mechanism called Cross Presenter Messaging thanks to which you can share a data between your controls using the publish/subscribe pattern.
For better explanation look here and here
I suggest to give the library a chance :)
In C# you can inherit from only one class and implement multiple interfaces.
This is allowed:
partial class myControl : SampleBase
partial class myControl : SampleBase, Interface1
partial class myControl : SampleBase, Interface1, Interface2, Interface3
This is NOT allowed:
partial class myControl : SomethingELSE, SampleBase
Try making SomethingELSE inherit from SampleBase if it satisfies your design. If not, then I suggest encapsulating SampleBase as a property of each control that needs it as it also suggested #DanM.