Visual Inheritance, Design-time support for extended custom controls - c#

I'm extending my own custom control, which extends the UserControl class.
I can see all the elements fine in the extending class' designer, but all the properties of the extended custom control appear disabled and when selecting its element with the mouse a "locked" icon appears.
How can I fix that? I would like to be able to modify these properties from the designer.
EDIT: Definition of the custom control, which extends from UserControl.
namespace Wizard
{
[Designer(typeof(Wizard.StepDesigner))]
[DefaultProperty("TitlePanel, NavigationPanel")]
public partial class Step : UserControl
{
public Step()
{
InitializeComponent();
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Title TitlePanel
{
get
{
return this.title1;
}
set
{
this.title1 = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel ContentPanel
{
get
{
return this.contentPanel;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Navigation NavigationPanel
{
get
{
return this.navigation1;
}
}
}
internal class StepDesigner : ParentControlDesigner
{
public override void Initialize(System.ComponentModel.IComponent component)
{
base.Initialize(component);
if (this.Control is Step)
{
Step control = (Step)this.Control;
this.EnableDesignMode(control.TitlePanel, "TitlePanel");
this.EnableDesignMode(control.ContentPanel, "ContentPanel");
this.EnableDesignMode(control.NavigationPanel, "NavigationPanel");
}
}
}
}

As I already pointed out in the comments, the modifiers of the properties were all set to private and changing them to protected and rebuilding the solution fixed the "problem".

Related

Error using class derived from C# CheckedListBox to deal with missing descenders

Following the Microsoft suggestion to deal with the problem of descenders not being visible on items shown in a CheckedListBox Object (https://msdn.microsoft.com/en-us/library/system.windows.forms.checkedlistbox.itemheight(v=vs.110).aspx)
public sealed class MyListBox : CheckedListBox
{
public MyListBox()
{
ItemHeight = 20;
}
public override int ItemHeight { get; set; }
}
If I add this code outside the class as follows:
namespace SetTags
{
public partial class SetTags : Form
{
....
}
public sealed class MyListBox : CheckedListBox
{
public MyListBox()
{
ItemHeight = 20;
}
public override int ItemHeight { get; set; }
}
}
I can see MyListBox in the list of SetTags components in Toolbox and am able to add it to a form in design view, and set its name to chkListTags2.
However, when I try to build the project I get an error as follows:
SetTags.Designer.cs(55,45,55,54): error CS0426:
The type name 'MyListBox' does not exist in the type 'SetTags.SetTags'
Viewing SetTags.Designer.cs I see the problem is in the line
this.chkListTags2 = new SetTags.MyListBox();
If I edit this to
this.chkListTags2 = new MyListBox();
the build error goes away but recurs when SetTags.Designer is automatically rebuilt.
Is there a way of adding the new sealed class without producing the build error?
I am using VS 2013 in Win10 environment.

Call Refresh event of grid Polymorphically C#

I have a main window in WPF and it contains:
A Tab Control having different tabs. Each tab has a different control in it and contains a data grid.
A frame control - it also has different controls respectively for data entry.
A Refresh Button (Yet to implement)
I have implemented the tab controls and frame for data entry successfully but problem is I cannot refresh the tab control until I switch across the tabs. I want to have a central Refresh button on main-window (one I aforementioned).
Can anyone guide me how can I do it?
And since tab's current object type will only be decided at the Run-time, so is it Polymorphism?
You can use an interface for all the usercontrols:
public interface IRefreshAble
{
void Refresh();
}
public interface ICanDeleteItem
{
void Delete(/*parameters omitted*/);
bool CanDelete { get; }
}
public interface IHoldATypedItem ///sorry for bad name
{
Type TheType { get; }
}
Then you implement this interface by the usercontrols:
public class TheUserControl : UserControl, IRefreshAble, ICanDeleteItem, IHoldATypedItem
{
public void Refresh()
{
//Your refreshcode
}
public bool CanDelete {get { /*code that indicates if an item can be deleted*/ } }
public void Delete(/*parameters ommited*/)
{
if(CanDelete)
{
//Delete Item
}
}
public Type TheType { get { return typeOf(Employee); } }
// otherstuff
}
Now you can put all of your UserControls(for example) in a List<IRefreshAble> and do stuff like:
foreach(IRefreshAble item in theList)
{
item.Refresh();
}
If you have more than this Refresh() method common for all Usercontrols you can just expand the interface for this members and get the polymorphism you need.

Hide my user control in designer form

How i can hide my user control from designer form, to show in bottom of designer, like timers or openFileDialog...
What i want to do is a custom menuStrip, with animation, progressBar, dateTimePicker, and so on. But i don't want to be visible in designer, just like normal menuStrip.
I tried to make my user control as component, but if i do it, i lose others.
An example would be :
public class ExampleForm : Form
{
public ExampleForm()
{
CustomMenuStrip a = new CustomMenuStrip();
a.Items.Add(new CustomMenuStripItem()
{
///Stuff
});
}
}
public class CustomMenuStrip : UserControl
{
public List<CustmMenuStripItem> Items;
public CustomMenuStrip()
{
//Do Stuff
}
}
public class CustomMenuStripItem : UserControl
{
public CustomMenuStripItem()
{
//Do Stuff
}
}
Any ideas?
Thank's in advance.
Andrei

Component - Subclass event c#

I have a class what I would like to close into a component. I try to make it work, based on the following code,
The issue is, that the properties are editable and viewable in the property browser & the Test Event is viewable but it cannot be filled form the property browser, just from the code.
How can I solve this anomaly?
namespace TestComponents
{
public partial class Test: Component
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public SubClass SubClass { get; set; }
public Test()
{
InitializeComponent();
SubClass = new SubClass();
}
}
public delegate void TestEventHandler(Object sender, TestEventArgs e);
public class TestEventArgs: EventArgs
{
public Boolean Test { get; set; }
public TestEventArgs(Boolean ATest): base()
{
Test = ATest;
}
}
[TypeConverterAttribute(typeof(System.ComponentModel.ExpandableObjectConverter))]
public class SubClass
{
public Boolean TestProperty { get; set; }
public event TestEventHandler TestEvent;
protected virtual void OnTestEvent(TestEventArgs e)
{
if (TestEvent != null)
TestEvent(this, e);
}
}
}
Problem solved. If the subclass inherited from Component, the Visual Studio can manage "subclass events" well.
Suspect the property editor doesn't know how it should handle input related to the complex TestEventArgs class, so you can't edit in in the Visual Studio property editor.
You could have a look at writing a Custom UI Type Editor and then specify the custom editor by using the EditorAttribute:
[EditorAttribute(typeof(YourCustomEditor),typeof(System.Drawing.Design.UITypeEditor))]

User Control as container at design time

I'm designing a simple expander control.
I've derived from UserControl, drawn inner controls, built, run; all ok.
Since an inner Control is a Panel, I'd like to use it as container at design time. Indeed I've used the attributes:
[Designer(typeof(ExpanderControlDesigner))]
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
Great I say. But it isn't...
The result is that I can use it as container at design time but:
The added controls go back the inner controls already embedded in the user control
Even if I push to top a control added at design time, at runtime it is back again on controls embedded to the user control
I cannot restrict the container area at design time into a Panel area
What am I missing? Here is the code for completeness... why this snippet of code is not working?
[Designer(typeof(ExpanderControlDesigner))]
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class ExpanderControl : UserControl
{
public ExpanderControl()
{
InitializeComponent();
....
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
internal class ExpanderControlDesigner : ControlDesigner
{
private ExpanderControl MyControl;
public override void Initialize(IComponent component)
{
base.Initialize(component);
MyControl = (ExpanderControl)component;
// Hook up events
ISelectionService s = (ISelectionService)GetService(typeof(ISelectionService));
IComponentChangeService c = (IComponentChangeService)GetService(typeof(IComponentChangeService));
s.SelectionChanged += new EventHandler(OnSelectionChanged);
c.ComponentRemoving += new ComponentEventHandler(OnComponentRemoving);
}
private void OnSelectionChanged(object sender, System.EventArgs e)
{
}
private void OnComponentRemoving(object sender, ComponentEventArgs e)
{
}
protected override void Dispose(bool disposing)
{
ISelectionService s = (ISelectionService)GetService(typeof(ISelectionService));
IComponentChangeService c = (IComponentChangeService)GetService(typeof(IComponentChangeService));
// Unhook events
s.SelectionChanged -= new EventHandler(OnSelectionChanged);
c.ComponentRemoving -= new ComponentEventHandler(OnComponentRemoving);
base.Dispose(disposing);
}
public override System.ComponentModel.Design.DesignerVerbCollection Verbs
{
get
{
DesignerVerbCollection v = new DesignerVerbCollection();
v.Add(new DesignerVerb("&asd", new EventHandler(null)));
return v;
}
}
}
I've found many resources (Interaction, designed, limited area), but nothing was usefull for being operative...
Actually there is a trick, since System.Windows.Forms classes can be designed (as usual) and have a correct behavior at runtime (TabControl, for example).
ParentControlDesigner doesn't know what you want do. It only knows you want your UserControl to be a container.
What you need to do is implement your own designer which enables design mode on the panel:
using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace MyCtrlLib
{
// specify my custom designer
[Designer(typeof(MyCtrlLib.UserControlDesigner))]
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
// define a property called "DropZone"
[Category("Appearance")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel DropZone
{
get { return panel1; }
}
}
// my designer
public class UserControlDesigner : ParentControlDesigner
{
public override void Initialize(System.ComponentModel.IComponent component)
{
base.Initialize(component);
if (this.Control is UserControl1)
{
this.EnableDesignMode(
(UserControl1)this.Control).DropZone, "DropZone");
}
}
}
}
I learned this from Henry Minute on CodeProject. See the link for some improvements on the technique.
In addition to the answer above. It is mentioned in the comments, that the user is able to drag the WorkingArea. My fix for that is to include the WorkingArea panel in another panel, setting it to Dock.Fill. To disallow the user to change it back, I have created a class ContentPanel that overrides and hides the Dock property:
class ContentPanel : Panel
{
[Browsable(false)]
public override DockStyle Dock
{
get { return base.Dock; }
set { base.Dock = DockStyle.Fill; }
}
}
For me, this makes it sufficiently safe. We are only using the control internally, so we mainly want to prevent developers from accidently dragging things around. There are certainly ways to mess it up anyway.
To prevent the working area from being moved/resized in the designer you have to create a class for that working area that hides the Location, Height, Width, Size properties from the designer:
public class WorkingArea : Panel
{
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new Point Location
{
get
{
return base.Location;
}
set
{
base.Location = value;
}
}
...
}

Categories

Resources