Related
I am trying some different things using MVVM. In our ViewModel properties which are bind to View are public. I am taking example of a button binding. Here is a simple sample.
View.xaml:
<Button Content="Test Button" Command="{Binding TestButtonCommand}" />
ViewModel.cs
private ICommand _testButtonCommand;
public ICommand TestButtonCommand
{
get { return _testButtonCommand?? (_testButtonCommand= new RelayCommand(SomeMethod)); }
}
Here my question is that can we make TestButtonCommand internal instead of public? Internal means it is accessible to current project so their should not be any problem doing that? But when I tried to do that it didn't worked. Adding a breakpoint in getter was not hit. So why we cannot make it internal?
Here is the link from msdn.
http://msdn.microsoft.com/en-us/library/ms743643.aspx
The properties you use as binding source properties for a binding must
be public properties of your class. Explicitly defined interface
properties cannot be accessed for binding purposes, nor can protected,
private, internal, or virtual properties that have no base
implementation.
Why we cannot do this?
In case of access internal is same as public if working in the same project. Then why we cannot use internal here? There must be a reason that these should be public, and I am looking for that reason.
internal ICommand TestButtonCommand { ...... }
In case of access internal is same as public if working in the same
project. Then why we cannot use internal here. There must be a reason
that these should be public, and I am looking for that reason.
You have part of your answer in your question itself in the quote from Microsoft:
The properties you use as binding source properties for a binding must
be public properties of your class.
Presumably / speculatively, the reason for this is that internals can only be accessed within the same assembly and not from outside. Binding to internals doesn't work because binding is resolved by the WPF binding engine which is in a separate assembly PresentationFramework.dll.
Binding is only supported for public properties. MSDN reference:
http://msdn.microsoft.com/en-us/library/ms743643.aspx
As quoted in the reference
The properties you use as binding source properties for a binding must
be public properties of your class. Explicitly defined interface
properties cannot be accessed for binding purposes, nor can protected,
private, internal, or virtual properties that have no base
implementation.
The internal visibility is really only meaningful to the compiler and the IL verifier, because they know the full context of the member access; the WPF binding engine does not. It knows that a binding exists on a property; it has no idea who set the property. It could have been set in the XAML, or dynamically at runtime (technically, even if you set it in the XAML, it is still applied dynamically).
Since there is no way to enforce the access rules, allowing binding to internal properties would be equivalent to allowing binding to private properties, not public properties.
Obviously, it depends on what you're trying to achieve from this situation - you don't state what the overall aim is. I have just come across a similar problem with my code, and also happened upon a solution for my case.
One of my libraries contains helper objects with various properties, but when these are used in the application project, I only want to see the properties that are of any use to me - I wanted to hide, for example, the Command properties.
My solution to hide them from the 'user' of the library is to add the
<EditorBrowsable(EditorBrowsableState.Never)>
attribute to each property that bears little or no interest to me.
Hope that helps someone!
From http://msdn.microsoft.com/en-us/library/ms743643.aspx
For CLR properties, data binding works as long as the binding engine
is able to access the binding source property using reflection.
Otherwise, the binding engine issues a warning that the property
cannot be found and uses the fallback value or the default value, if
it is available.
Created internal property are breaking good OO design and are breaking encapsulation.
You can use internal set accessor (and public get accessor) for your case.
public ICommand SaveCommand
{
get;
internal set;
}
If you have a field encapsulated into a property, you should make it a rule to always access that field throught a property even inside your class. It's best practise.
It is not possible to bind to internal properties. You can make your class as internal though, if you do not want your class to be accessible outside the project.
Okay Stackers, I've spent a good couple of hours on this question, and I want to know if anybody has a definitive answer.
For all the research I've done, I can't find ANY difference between .Register and .RegisterAttached in Silverlight. Now, before you jump the gun and tell me that .RegisterAttached is used for attaching a DP to another class, try implementing an Attached Dependency Property using DependencyProperty.Register(). I have found not a single difference, and so I am at a loss as to what the difference is.
Furthermore, in my specific case, I'm attempting to extend the functionality of the Grid class, and want to give it some extra properties. As such, I've tried listing passing both typeof(Grid) and typeof(FluidLayoutManager) (the implementing class) as the ownerType parameter and it also seems to make very little difference... (I believe it does make a difference when I pass two custom classes from the same namespace. However when passing a Microsoft defined class vs. a custom class, I always have it showing up in the XAML as a DP of the custom class.)
Any clarification on this topic would be much appreciated, as I'm sitting here scratching my head, and wondering if there is any difference at all, or if Microsoft is just screwing with me once again.
Given the discussions flowing in comments I will try to do this one in plain English:
The main difference between Attached Dependency Properties and Dependency Properties (and therefore between .Register and .RegisterAttached) is that RegisterAttached allows the value to be assigned to any dependency object whereas Register only allows it to be attached to the class passed as the ownerType parameter.
As Haris Hasan mentions (deep in the comment thread), your example is using the only type allowed (i.e. CustomControl) and does not show you that the Attached version can be assigned to ANY dependency object.
e.g. you can do this with your Attached Dependency Property (but not a plain DP):
<Grid local:AttacherClass.ADP1="1" x:Name="LayoutRoot" Background="White">
</Grid>
The best reference for ADPs I can find is this one: http://msdn.microsoft.com/en-us/library/ms749011.aspx
We used ADPs as the basis of a localisation system, so that translations could be parasited onto objects during load rather than using horrendously long bindings. Couldn't do that with DPs
Update:
I would also like to clarify that the parent limitation applies to XAML based use of the attribute. From code the parent limitation apparently does not apply.
It is wrong to believe that "RegisterAttached allows the value to be assigned to any dependency object whereas Register only allows it to be attached to the class passed as the ownerType parameter". Here is a perfectly working example of an attached property registered with Register:
class FooPropertyDeclaringType
{
public static readonly DependencyProperty FooProperty =
DependencyProperty.Register("Foo", typeof(int), typeof(FooPropertyDeclaringType));
}
class SomeUnrelatedType : DependencyObject { }
class Program
{
static void Main()
{
var obj = new SomeUnrelatedType();
obj.SetValue(FooPropertyDeclaringType.FooProperty, 10);
Debug.Assert(10 == (int)obj.GetValue(FooPropertyDeclaringType.FooProperty));
}
}
Reflector shows that the only difference between Register and RegisterAttached is that the Register throws out much of the supplied metadata and only preserves it for the instances of registering class (via OverrideMetadata). It means that attributes such as Inherits and various update notifications usually specified in the metadata do not work on properties registered with Register and attached to objects of other types (other than the registering type). So Register is actually a stripped down version of RegisterAttached. It was probably made this way for performance reasons.
In the example linked by Haris Hasan in the comments to his answer, if you change RegisterAttached to Register, the buttons stop moving (because the property no longer provides AffectsParentArrange metadata for Button type) but they are nevertheless redrawn in their new locations when you resize the window. But if you add the same metadata to the Button type after a call to InitializeComponent():
RadialPanel.AngleProperty.OverrideMetadata(
typeof(Button),
new FrameworkPropertyMetadata(
0.0, FrameworkPropertyMetadataOptions.AffectsParentArrange));
then everything works again as if RegisterAttached was called.
They might not be much different as far as implementation is concerned but they are difference in actions i.e. they are different in what they do and are used for.
Simple Register is used for simple dependency properties which you usually are used for bindings and validations so they are normal CLR properties with some additional magic which helps in WPF
RegisterAttached is normally used where you want to expose a property that can be accessed and set in the child class like DockPanel where children of control tells parent where they want to be placed using Dock.Left or Dock.Right. So they are kind of special dependency properties which can be accessed in the child controls (which is not the case with simple Register properties) and they(in case of DockPanel) helps parent control in displaying children
In short one cay say Register is used registering dependency properties which are used in same class while RegisterAttached is used for registering special dependency properties called attached properties and they are used and accessed by classes other than one which defined it
This is a good explanation of Attached Properties and what cannot be achieved through simple DP
If you register with RegisterAttached, it becomes global as a property in the store of any DependencyObject, i.e. you could SetValue on any Dependency Object
If you use Register when Get/Setvalue are called there will be a check that the call is prom an object that is castable to the registering type.
An Example of a property that behaves like RegisterAttached is Grid.Row and Grid.Column.
So exactly what is 'ownerType' used for in RegisterAttached? This issue has been nagging at me for a few years, so I finally took a closer look at 4.6.1 code in WindowsBase.
For any DependencyProperty, attached or otherwise, what it eventually comes down to is what type of PropertyDescriptor WPF obtains for late-bound XAML access, and this isn't determined until the first time (on a per type/property pairing basis) such access is attempted. This deferral is necessary because PropertyDescriptor encapsulates a property bound to a specific type, whereas the point of attached properties is to avoid exactly this.
By the time XAML access occurs, the Register(...) versus RegisterAttached(...) distinction has been lost to the mists of (run)time. As others have noted on this page, 'DependencyProperty' itself doesn't encode a distinction between an attached vs. non- variety. Every DP is assumed to be eligible for either usage, subject only to what can be figured out at runtime.
For example, the .NET code below seems to rely on not finding a matching instance property on the 'tOwner' type as the first requirement for allowing attached access. To confirm this diagnosis, it then checks whether 'tOwner' exposes one of the static access methods. This is a vague check insofar as it doesn't verify the method signatures. Those signatures only matter for XAML access; all actual runtime targets for the attached property must be DependencyObjects, which WPF accesses through DependencyObject.GetValue/SetValue whenever possible. (The VS Designer reportedly does use the static accessors, and your XAML won't compile without them)
The relevant .NET code is the static function DependencyPropertyDescriptor.FromProperty, shown here with my own comments (summary below):
internal static DependencyPropertyDescriptor FromProperty(DependencyProperty dp, Type tOwner, Type tTarget, bool _)
{
/// 1. 'tOwner' must define a true CLR property, as obtained via reflection,
/// in order to obtain a normal (i.e. non-attached) DependencyProperty
if (tOwner.GetProperty(dp.Name) != null)
{
DependencyPropertyDescriptor dpd;
var dict = descriptor_cache;
lock (dict)
if (dict.TryGetValue(dp, out dpd))
return dpd;
dpd = new DependencyPropertyDescriptor(null, dp.Name, tTarget, dp, false);
lock (dict)
dict[dp] = dpd;
/// 2. Exiting here means that, if instance properties are defined on tOwner,
/// you will *never* get the attached property descriptor. Furthermore,
/// static Get/Set accessors, if any, will be ignored in favor of those instance
/// accessors, even when calling 'RegisterAttached'
return dpd;
}
/// 3. To obtain an attached DependencyProperty, 'tOwner' must define a public,
/// static 'get' or 'set' accessor (or both).
if ((tOwner.GetMethod("Get" + dp.Name) == null) && (tOwner.GetMethod("Set" + dp.Name) == null))
return null;
/// 4. If we are able to get a descriptor for the attached property, it is a
/// DependencyObjectPropertyDescriptor. This type and DependencyPropertyDescriptor
/// both derive directly from ComponentModel.PropertyDescriptor so they share
/// no 'is-a' relation.
var dopd = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, tTarget);
/// 5. Note: If the this line returns null, FromProperty isn't called below (new C# syntax)
/// 6. FromProperty() uses the distinction between descriptor types mentioned in (4.)
/// to configure 'IsAttached' on the returned DependencyProperty, so success here is
/// the only way attached property operations can succeed.
return dopd?.FromProperty(dopd);
}
Summary: When calling RegisterAttached to create an attached DependencyProperty, the only thing 'ownerType' is used for is to identify a type which defines appropriate static Get/Set accessors. At least one of those accessors must exist on 'ownerType' or XAML attached access will not compile or silently fail. Although RegisterAttached does not fail in this case, and instead successfully returns a defunct DP. For DPs intended for attached use only, 'tOwner' doesn't have to derive from DependencyObject. You can use any regular .NET class, static or non-static, and in fact can even be a struct!
Ok so I'm currently working with a set of classes that I don't have control over in some pretty generic functions using these objects. Instead of writing literally tens of functions that essentially do the same thing for each class I decided to use a generic function instead.
Now the classes I'm dealing with are a little weird in that the derived classes share many of the same properties but the base class that they are derived from doesn't. One such property example is .Parent which exists on a huge number of derived classes but not on the base class and it is this property that I need to use.
For ease of understanding I've created a small example as follows:
class StandardBaseClass {} // These are simulating the SMO objects
class StandardDerivedClass : StandardBaseClass {
public object Parent { get; set; }
}
static class Extensions
{
public static object GetParent(this StandardDerivedClass sdc) {
return sdc.Parent;
}
public static object GetParent(this StandardBaseClass sbc)
{
throw new NotImplementedException("StandardBaseClass does not contain a property Parent");
}
// This is the Generic function I'm trying to write and need the Parent property.
public static void DoSomething<T>(T foo) where T : StandardBaseClass
{
object Parent = ((T)foo).GetParent();
}
}
In the above example calling DoSomething() will throw the NotImplemented Exception in the base class's implementation of GetParent(), even though I'm forcing the cast to T which is a StandardDerivedClass.
This is contrary to other casting behaviour where by downcasting will force the use of the base class's implementation.
I see this behaviour as a bug. Has anyone else out there encountered this?
I see this behaviour as a bug.
This behavior is correct. Since your method DoSomething is constraining T to StandardBaseClass, you only have access to the specific methods of StandardBaseClass, not any methods or properties of a derived class. Since StandardBaseClass does not have a Parent property, this is invalid, and should be invalid, by design.
There are two potential options here - You can use reflection to pull out the Parent property, or use C# 4's dynamic type, and treat this as a dynamic object. Both bypass the standard type checking in the compiler, however, so will require you to do extra type checking at runtime to verify that the Parent property exists.
Create an interface that contains the Parent property. Have each class that has a Parent property implement that interace. You will then be able to create a generic method that accepts a parameter of type IHaveParent, and it will do the right thing.
For anyone that is interested an succinct answer to this situation is answered by Stephen Cleary on msdn here:
http://social.msdn.microsoft.com/Forums/en-AU/csharpgeneral/thread/95833bb3-fbe1-4ec9-8b04-3e05165e20f8?prof=required
To me this is a divergence in the class hierarchy. By this this I mean that either the base class has parent, or the derived classes with Parent are derived from an abstract child of the base.
Lol as John says, an interface as opposed to an abstract class is sufficient too.
You idea won't work because the compiler can never guarantee that the base class actually would have such a property. And it won't just select the "right" one based on if it has it or not.
The only way you can do this is using reflection and then test at runtime if the requested property exists on the inspected class. You have to judge yourself if that is a viable way to do for your project (reflection is slow and requires maximum rights).
This is correct, as the compiler only knows that it can bind to your type as a StandardBaseClass. The binding is not done at runtime (where it could potentially decide to use the StandardDerivedClass overload.
If you know that it's a StandardDerivedClass, then why not just cast it as such?
object Parent = ((StandardDerivedClass)foo).Parent;
It's a bit ugly, but you can accomplish this using a Registration system, where you register delegates for different possible derived classes that expose the 'shared' property/method and then use something like a Dictionary<Type,Func<SomeT>> to store the delegates. If you know all of the derived types ahead of time and don't have to load plug-ins or the like, you can also use the classic ugly if/else-if structure. Either way you're basically creating your own substitute for what should have been supported by the virtual method table.
I have a class I am working with:
public sealed class WorkItemType
It's ToString is weak (Just shows Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemType).
Is there any way to override this to show the name of the WorkItemType?
Normally I would just aggregate the value in a new class, but I am using this for bindings in WPF (I want to have a list of WorkItemTypes in a combo box and assign the selected value to a bound WorkItemType variable.)
I think I am out of luck here, but I thought I would ask.
A fairly neat way to do it might be to add an extenesion method to the WorkItemType object. Something like this:
public static class ToStringExtension
{
public static string MyToString(this WorkItemType w)
{
return "Some Stuff"
}
}
Then you could call something like
WorkItemType w = new WorkItemType;
Debug.WriteLine(w.MyToString();)
Do you need to override ToString? If you are in control of the code where the object is displayed, you can always provide a FormatWorkItemType method, or something to that effect.
WPF provides a few different built-in ways to do this right in the UI. Two I'd recommend:
You can use ComboBox's
DisplayMemberPath to display a single
property value but still select from
the WorkItemType objects.
If you want to display a composite of
a few properties you can change the
ComboBox's ItemTemplate to make it
look pretty much however you want -
formatting text, adding borders,
colors, etc. You can even set up the
DataTemplate to automatically be
applied to any WorkItemType object
that gets bound anywhere in your UI
(same basic effect from UI
perspective as changing ToString) by
putting it into Resources and giving
it only a DataType with no x:Key.
You're out of luck :-(
You could write your own class that wraps the WorkItemType and delegate down to it (a proxy) expect for the ToString:
class MyWorkItemType
{
private WorItemType _outer;
public MyWorkItemType(WorkItemType outer)
{
_outer=outer;
}
public void DoAction()
{
_outer.DoAction();
}
// etc
public override string ToString()
{
return "my value"
}
}
I don't have any C# knowledge, but can't you wrap your extended class inside another class? Proxy all method calls to the extended class, except toString(), Also very hackish, but I thought I'ld bring it up anyway.
Doing some sorta magic with reflection is probably your only hope. I know you can instantiate private constructors with it, so maybe you can override a sealed class... Note, this should be your last resort if there is seriously no other way. Using reflection is a very hackish/improper way of doing it.
In addition to the other WPF-specific answer you could use an IValueConverter in the binding to format / display the WorkItemType however you want. This has an advantage of being reusable (if you want to display the object in some other control, for instance.)
There are many examples of using converters here. This other question should be pretty similar to the ComboBox usage mentioned here. The answers note that you can either make the converter work on the entire collection of objects, or work on one item at a time. The latter might be the more reusable approach.
So we have a C# WinForms project with a Form that contains a bazillion UserControls. Each UserControl naturally exposes all the UserControl methods, properties, etc. in addition to its own specific members.
I've been thinking that one way to reduce the complexity of dealing with these UserControls is to access them through an interface. So instead of drag-and-drop to put the UserControl on the form, something like this in the constructor:
public class MyGiantForm
{
ICustomerName cName;
public MyForm()
{
InitializeComponent();
var uc = new SomeCustomerNameUserControl();
this.Controls.Add(uc);
cName = uc;
}
}
SomeCustomerNameUserControl implements ICustomerName, naturally, and ICustomerName contains the specific properties I really care about (say, FirstName and LastName). In this way I can refer to the UserControl through the cName member and, instead of being bowled over by all the UserControl members, I get only those in ICustomerName.
All well and good, but the problem is that if I do it this way, I can't see SomeCustomerNameUserControl in the Designer. Does anybody know I way I can do this but still see the UserControl on the form's design surface?
EDIT: One way to do this, which isn't overly complicated, is to put the controls on a base form. By default (in C#) the control members are private. Then I create a property for each control exposing it through the interface.
However, I'd be interested in some other way to do this, even if it's more complex. There seems to be some way to do it with IDesignerHost, but I can't find any applicable examples.
If SomeCustomerNameUserControl is defined like this:
class SomeCustomerNameUserControl : UserControl, ICustomerName
{
}
You can still drop this control in the designer (which creates someCustomerNameUserControl1) and do this whenever you need to:
ICustomerName cName = someCustomerNameUserControl1;
Maybe I'm missing something, but I think it's that simple.
There's a way to accomplish what you want -- hiding the members you don't want to see -- but make it apply automatically, without requiring others' cooperation in terms of them using a custom interface. You can do it by reintroducing all the members you don't want to see, and tagging them with attributes.
This is what Windows Forms does when, for example, a base-class property doesn't mean anything for a particular descendant. For example, Control has a Text property, but a Text property is meaningless on, say, a TabControl. So TabControl overrides the Text property, and adds attributes to its override saying "By the way, don't show my Text property in the Property Grid or in Intellisense." The property still exists, but since you never see it, it doesn't get in your way.
If you add an [EditorBrowsable(EditorBrowsableState.Never)] attribute to a member (property or method), then Intellisense will no longer show that member in its code-completion lists. If I'm understanding your question correctly, this is the big thing you're trying to achieve: make it hard for application code to use the member by accident.
For properties, you probably also want to add [Browsable(false)] to hide the property from the Property Grid, and [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] to prevent the designer from writing the property's value to the .designer.cs file.
These will make it very difficult to accidentally use the method/property. They're still not a guarantee, though. If you do need a guarantee, then throw in an [Obsolete] attribute too, and build with "Treat warnings as errors" -- then you're taken care of.
If the base member is virtual, you probably want to override it, and have your override simply call base. Don't throw an exception, since the overridden member will probably be called by the base class during the normal course of events. On the other hand, if the base member isn't virtual, then you want to use "new" instead of "override", and you can decide whether your implementation should call base, or just throw an exception -- nobody should be using your reintroduced member anyway, so it shouldn't matter.
public class Widget : UserControl
{
// The Text property is virtual in the base Control class.
// Override and call base.
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("The Text property does not apply to the Widget class.")]
public override string Text
{
get { return base.Text; }
set { base.Text = value; }
}
// The CanFocus property is non-virtual in the base Control class.
// Reintroduce with new, and throw if anyone dares to call it.
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("The CanFocus property does not apply to the Widget class.")]
public new bool CanFocus
{
get { throw new NotSupportedException(); }
}
// The Hide method is non-virtual in the base Control class.
// Note that Browsable and DesignerSerializationVisibility are
// not needed for methods, only properties.
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("The Hide method does not apply to the Widget class.")]
public new void Hide()
{
throw new NotSupportedException();
}
}
Yes, this is a fair bit of work, but you only have to do it once... per member, per class... umm, yeah. But if those base-class members really don't apply to your class, and having them there will cause confusion, then it may be worth going to the effort.
'I want ICustomerName to be the only option for accessing the UserControl's variable. The idea is that a developer doesn't have to "just remember" to cast it.'
The problem you are having is that you have two completely divergent uses for your form and the controls it hosts. There is no trick built into Visual Studio or winforms which solves this neatly for you. It may be possible, but there is a much cleaner and object oriented way to separate the two methods of interacting with the controls.
If you want to hide the fact that these objects inherit from UserControl, and just want to treat them as IDoSomeThingYouShouldDealWith, you need to separate the logic that deals with the presentation concerns (designer + UI logic) from your business logic.
Your form class, should rightly deal with the controls as UserControls, docking, anchoring etc etc, nothing special here. You should put all the logic that needs to deal with ICustomerName.FirstName = etc into a completely separate class. This class doesn't care or know about fonts and layout, it just knows that there is another instance that can present a customer name; or a DateTime as a 'date of birth choosing' control properly etc.
This is a really lame example, but I have to go right now. You should be able to get the idea covered here in more detail:
public interface ICustomerName
{
void ShowName(string theName);
}
public partial class Form1 : Form, ICustomerName
{
public Form1()
{
InitializeComponent();
}
#region ICustomerName Members
public void ShowName(string theName)
{
//Gets all controls that show customer names and sets the Text propert
//totheName
}
#endregion
}
//developers program logic into this class
public class Form1Controller
{
public Form1Controller(ICustomerName theForm) //only sees ICustomerName methods
{
//Look, i can't even see the Form object from here
theForm.ShowName("Amazing Name");
}
}
After you add the UserControl using the designer, you can set GenerateMember to false in the Properties window to suppress generation of a member.
You could then use some other technique in the constructor to assign your cName reference, e.g.:
foreach(Control control in this.Controls)
{
cName = control as ICustomerName;
if (cName != null) break;
}
cName would then be the only reference to the UserControl.
You could write an extension method that would allow you to return any controls on the form that implement an interface.
public static class FormExtensions
{
public static IDictionary<string, T> GetControlsOf<T>(this Form form)
where T: class
{
var result = new Dictionary<string, T>();
foreach (var control in form.Controls)
{
if ((control as T) != null)
result.Add((control as T).Tag, control as T);
}
return result;
}
}
Then in your form you could call it whereever you want by:
this.GetControlsOf<ICustomerName>()["NameOfControlHere"];
In the event that it returns more than one user control you would need to handle that some how, perhaps by adding Tag property to the interface to uniquely keep track of each user control or something, like so
public partial class UserControl1 : UserControl, ICustomerName
{
public string Tag { get { return this.Name; } }
}
You can then drag and drop the user controls onto your form from the designer. Tag will always return the name of your control, which will allow you to directly access the control through the IDictionary's interface. You're developers could put whatever unique identifier they want in the name of the control, and it would carry through to the interface.
Also, it should be noted that this approach will ALSO allow you to use this on ALL forms in your solution.
The only other thing you would need to do is set your GenerateMember to false.
you could as well do as Bob said but assign all your member variables in the constructor, then you have it in one place.
It almost seems like you want to implement a mediator pattern. Instead of having to deal with each of the bazillion UserControls directly, you'd interact with them through the mediator. Each mediator would define the slim interface you want to see from each control. This would reduce the overall complexity by making your design more explicit and concise. For example, you wouldn't need the 20 properties and 50 methods available on one of your controls. Instead you'd deal with the mediator for that control which defines the 2 properties and 5 methods you really care about. Everything would still show up in the designer, but other parts of your app would not be interacting with those controls -- they'd interact with the mediators.
One of the big advantages to this approach is it greatly simplifies your maintenance. If you decide the MyCrappyUserControl needs to be rewritten because the implementation is bad, you just need to update the mediator class for that control. All the other classes that interact with the control do so through the mediator and would be unchanged.
Ultimately it comes down to discipline: you and your team need to be disciplined enough to use the mediators/interfaces/whatever instead of the directly hitting the controls. Institute an over the shoulder code review by a leader programmer if your team is on the low end of the discipline scale.
Assume that MyUserControl is defined like this:
class MyUserControl : UserControl, IMyInterface
{
// ...
}
Then in your form, you should have something like this:
public class MyForm : Form
{
IMyInterface cName;
public MyForm()
{
InitializeComponent();
cName = new MyUserControl();
Controls.Add((UserControl)cName);
}
}
This way, cName is the only way to access this instance of our usercontrol.