I have a winforms application, in which I need sometimes to indirectly inherits From the class Form
Example
public class FormTest : TemplateForm
{
}
public class TemplateForm : Form
{
}
The problem is that the design of FormTest is disabled because it didn't inherit directly from Form class.
When iclick into Show Call Stack I had
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.EnsureDocument(IDesignerSerializationManager manager)
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32 fReload)
So, How can I change this behaviour and make the design enable , I mean how can I make the design of the form enable when the Form class is detected in its inheritence tree?
The feature you're asking for is Visual inheritance, make sure you have given at least protected access for the controls you need to access in the derived class. Then you'll be able to access them in designer.
Note:Nevertheless some controls like DataGridView, TableLayoutPanel etc prevents them from being edited through derived class via designer. Am not sure why.
Related
I have 2 forms that inherit a control from the class below:
public class AInbox: Form
{
public FlowLayoutPanel InboxItems;
}
The forms inherits as such:
public partial class Inbox : AInbox
{
...
}
In the Designer.cs file i commented out the original "InboxItems" control declaration and everything compiles and runs fine... except the GUI designer. When i open the Designer I get the error "The variable 'InboxItems' is either undeclared or was never assigned."
Is there any way to use this inheritance and still have the designer work?
I'd recommend against inheriting a form with generated code (like you're doing with Inbox).
If you want the child class (Inbox) to add additional controls, I wouldn't use the designer directly on the child class, because I don't think the visual studio form designer will play nicely when half of the form was designed in the parent class. If you need to reuse certain parts of your form in a different form, you might want to consider moving that part of the form to a separate user control. You can use the designer on this user control and later put the user control in the forms.
If you just need to have the same form, keep an instance of the form in your other class. Move your logic away from your form (view) and in your other class (controller).
I have an issue, and I don't know if I can do that, or if there is another way to do that. I have an abstract class called "BasePage", it is my .NET Standard library, so I can't access to System.Windows namespace. Its declaration is:
public abstract class BasePage<VR> where VR : new()
EDIT: The class above has a public property to access to VR
So now, for each platform (WPF, Xamarin, etc) I have to create its own implementation of the class begin VR the content control of each platform (UserControl for WPF, for example). I already did it and this is:
public class WindowsBasePage : BasePage<UserControl>
Now, every time I want to create a page to add content to a window, I have to create something like this:
public partial class UserPassPage : WindowsBasePage
{
public UserPassPage()
{
InitializeComponent();
}
}
The problem becomes when I have to set it in the XAML file (the View). I can create it and it builds:
<local:WindowsBasePage x:Class="Bitture.AppManager.Manager.UserPassPage"
[...]
xmlns:local="clr-namespace:Bitture.AppManager.Manager"
mc:Ignorable="d" >
</local:WindowsBasePage>
but I can't add components (like buttons, text, grids, stackpanels, etc). I want to know If I can do it with my current code or there is something I have to change. Because I have to access to the generic type WindowsBasePage that inherits from
class WindowsBasePage : BasePage<UserControl>
I am not sure what you are trying to do here but you can't add UIElements to a custom class of yours that doesn't inherit from any of the common WPF base classes such as for example Panel or ContentControl, and expect it to be rendered as a UserControl or some other WPF control.
This won't work. WPF knows about how to render WPF controls but it doesn't know how to render a custom BasePage<UserControl>.
I need to create a custom User Control with generics because I have a BindingSource with a data source of type T
public partial class ABMControl<T> : UserControl
{
public ABMControl()
{
InitializeComponent();
this.bindingSource.Datasource = typeof(T);
}
}
In the form designer the custom user control does not appear in toolbox because is generic.
What is the solution?
It's expected behavior for toolbox.
When dropping a control from toolbox onto your form, you are commanding the designer to create an instance of that control. You cannot create an instance of GenericControl<T> without determining T. Instead you need an instance of GenericControl<SomeClass>.
So it completely makes sense the generic control doesn't appear in toolbox because it has no usage in designer and designer doesn't know what type should it use for generic parameter when creating instance.
Also about designer, considering this post: Generic Base Class for UserControl starting from VS2015.1, Windows Forms Designer shows classes which have generic base classes without any problem. The following class will be shown in designer without any problem:
public class SomeClassControl:GenericControl<SomeClass>
{
}
For older versions of Visual Studio, use the workaround which is described in the linked post:
public class SomeClassControl:SomeClassControlBase
{
}
public class SomeClassControlBase:GenericControl<SomeClass>{}
I have a lot of different UserControls and would like to maintain consistent UI settings (mainly colors and fonts). My first try was this:
public class UISettings
{
//...
public void SetupUserControl(ref UserControl ctrl)
{
ctrl.BackColor = this.BackColor;
}
}
to be called in every control like this:
settings.SetupUserControl(ref this);
As this is read-only it cannot be passed by ref argument so this does not work. What are other options to keep consistent UI without manually changing properties for every item?
Inheritance! If you have a form or control that will constantly be using the same styles and you want to set that as your base, just create your own user controls that inherit from a form/control. By default all of your forms will inherit from "Form". Instead of inheriting from the default form, create a new user control that inherits from Form, and then have that as your base class.
CustomForm : Form // Your custom form.
Form1 : CustomForm // Inherit from it.
...the same works for components. If you want a button to have the same styles across the board, create a user control and have it inherit from the button control -- then use the custom control.
Whenever you want to make a change to your base styles, or any settings, simply change your custom controls settings -- your new forms/controls will automatically be updated!
Do the same thing. Don't pass it by ref. UserControl is a reference object already, so there's no need to pass it into your method using the ref keyword.
You may also want to consider a recursive method that will find all the UserControls on the form and pass it into your method.
How about a base class which provides such settings?
Two answers:
You don't need ref, controls are objects are reference types. Just drop it.
Create a Base UserControl and derive your controls form that base. You can still do that, just edit the class definitions of the controls. For new controls you can follow the Wizard.
A tip: setup the styling in the baseControl. Then make sure the derived controls don't override, the best way to do that is scanning the *.Designer.cs files and remove all settings that you know should come from the base.
An application I'm working will have a number of forms with a lot of shared functionality. For instance, each form will have a DataGridView, many of the same buttons, much of the same UI code and so on.
I'd like to implement this by creating a base version of this common form, subclass it for all these very-similar-but-not-quite-the-same child forms, and tack on whatever additional controls and features I need for each of them.
I've already figured out that it helps to make the base form's controls protected because this allows things like anchoring to work propertly. However, I have yet to find a way to automatically make the derived forms the same size as the base form.
Experience tells me there should be a simple way to do this. While it's not much of a problem to just type in the required size by hand for every derived form right after creating it, I'd prefer to make everything as clean, simple, and automatic as possible.
I find it interesting that your derived forms do not automatically inherit the size from their base form, because this should work without you having to do anything about it.
Suspected cause of your problem:
I suspect your problem results from the fact that you're using Visual Studio's Forms Designer to edit the forms. Whenever you've edited a form, Windows Forms Designer generates the required code in the InitializeComponent method of your forms. Among all the generated code are assignments that set a form's size, even if it is identical to the base form's size. Therefore you might have to manually comment out those assignments if you want your derived form to have the same size as the base form, even when you change the base form's size after creating the derived forms. (However, I don't know if that might lead to further problems with the controls' positioning & layouting.)
// Code to be commented out in your derived form's InitializeComponent method:
this.AutoScaleDimensions = new System.Drawing.SizeF(...);
this.ClientSize = new System.Drawing.Size(...);
Once these lines are commented out, the size as set in your base form's InitializeComponent will be used for the derived form.
A workaround solution:
You can do the following so that you don't have to manually comment-out designer-generated code every time you've edited a form:
Create an form derived from your base form; let's call it FrozenBaseForm. You will derive all other forms from this class instead of directly from the base form. Now, in this "intermediate" class, you define a new property ClientSize:
public class FrozenBaseForm : BaseForm
{
new public SizeF ClientSize
{
get { return base.ClientSize; }
set { }
}
}
This will cause all assignments to ClientSize to have no effect at all and therefore preserve the size from the base form. This feels like a hack to tell the truth, but it seems to work. You might have to hide the Size property in the same way btw.
As said, derive your forms from FrozenBaseForm instead of from BaseForm directly:
public class DerivedForm1 : FrozenBaseForm { ... }
public class DerivedForm2 : FrozenBaseForm { ... }
...
Another option (last resort if all else fails):
As a last resort, you could simply forget about the Forms Designer and just define the derived forms manually in the code editor (though I personally would not want to do this):
public class DerivedForm : BaseForm
{
public DerivedForm()
{
// make all necessary changes to the base form:
...
}
}
public partial class derivedForm : baseForm
{
public derivedForm()
{
InitializeComponent();
this.Width = base.Width;
this.Height = base.Height;
}
}
Why not make the BaseForm set the size of itself?
public partial class BaseForm : Form
{
public BaseForm()
{
InitializeComponent();
// you could hardcode these or retrieve these values from a
// config file or something
this.Width = 640;
this.Height = 468;
}
}
Wouldn't this do what you want?