Access One User Control From Another User Control
I have a form, form1, that I have placed two user controls on, uc1 and uc2. Displaying a user control from code in the form is simple, uc1.Show(). My question is, how do I display one user control from code within another user control, i.e. uc2.Show() called from uc1 does not work. I have been doing some reading on delegates and events, but I am having a difficult time finding a good example. Any help would be appreciated.
AnthonyPosted Dec 1, 2010, 8:59 AM
I have it working now by doing the following:
1. create a public event EventHandler eventhandlername in uc1
2. in the button click method, I added the following:
3. Following InitializeComponent() for uc1, I added:
4. Then back on form1, I created a method that I would like to be called when btnShow on uc1 is clicked,
5. Finally, I registered uc1_eventhandlername as a listener
Is this the correct way to handle this task?
Sam HobbsPosted Nov 30, 2010, 6:38 PM
Your latest question is a little vague, so if my understanding is incorrect then we need clarification of what you are asking.
AnthonyPosted Nov 30, 2010, 3:09 PM
Does the delegate need to be added in form1, as in,
The protection level of ShowUC2 would not matter, but, btnShow.Click located on uc1 is not visible now either.
AnthonyPosted Nov 17, 2010, 4:54 PM
Sam HobbsPosted Nov 16, 2010, 5:23 PM
Zoran HorvatPosted Nov 16, 2010, 5:16 PM
Here is an application that I'm coding right now. I have a left pane on the form containing a tree structure with a hierarchy of different objects. Some of the objects are just directories, others have content that can be edited by 3-4 other specific controls. Now, I have a SelectedObjectChanged event of the tree control, and that event is handled by the containing control, which is in this case form. Then, form decides which control is specialized to edit particular object which has been selected, and then shows that control on the right and gives it the object to edit. That is in my view proper way to pass information between controls. Tree control doesn't know and should not know which other control is used for which kind of object. Tree control doesn't even know if particular object is editable at all. Its job is to show tree with directories and items in the directories in a way that is pleasant to the user. Thinking about internals of items is other control's job.
Examples that show opposite point - like having controls at the same level communicate directly with each other - are very rare and limited to very simple situations.
Sam HobbsPosted Nov 16, 2010, 5:02 PM
Sam HobbsPosted Nov 16, 2010, 4:57 PM
Zoran HorvatPosted Nov 16, 2010, 4:46 PM
My practice is to use designer for forms and to avoid it in user controls. Also, I'm never deriving control classes from UserControl but rather from Control directly. But both practices have come after years of practicing, so for novice and intermediate levels I'd say that designer is a better choice - less things to screw.
AnthonyPosted Nov 16, 2010, 3:22 PM
Zoran HorvatPosted Nov 16, 2010, 3:17 PM
AnthonyPosted Nov 16, 2010, 3:12 PM
Zoran HorvatPosted Nov 16, 2010, 3:05 PM
For example, suppose that you have one control showing directory tree, and another control showing file content. Tree control can raise event SelectedFileChanged, and viewer can subscribe to that event and then change own content when user selects different file. However, I would rather make parent form subscribe to SelectedFileChanged event, and then implement File property (get/set) in the viewer. Parent form would then, when SelectedFileChanged event is fired, set new value to the viewer's File property, which would force refresh of the viewer's content.
Treating objects as equal is not good in my opinion. I'm always trying to keep strict hierarchy of objects, so that every object reports to a single parent. In that way, data paths are simpler and more under control. Firing events among controls, and especially changing controls states, may lead to unexpected cascade effects and bugs that are hard to trace.
AnthonyPosted Nov 16, 2010, 2:41 PM
Sam HobbsPosted Nov 16, 2010, 2:30 PM
Putting a UserControl in another UserControl from the form is inconsistent with object-oriented programmming. I don't know what the requirements of your application are but it is likely that experienced developers would use the design that you seem to be using.
Zoran HorvatPosted Nov 16, 2010, 12:07 PM
This code requires reference to System.Drawing to operate. Compile it as console application.
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
class Program
{
class Poly : UserControl
{
public event EventHandler ControlHit;
public Poly()
{
DoubleBuffered = true; // don't flicker
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Rectangle rect = ClientRectangle;
List
points.Add(new Point(0, rect.Height / 2));
points.Add(new Point(rect.Width / 2, 0));
points.Add(new Point(rect.Width, rect.Height / 2));
points.Add(new Point(rect.Width / 2, rect.Height));
e.Graphics.FillPolygon(Brushes.DarkBlue, points.ToArray());
string hit = _hitPoint.ToString("0");
SizeF textSize = e.Graphics.MeasureString(hit, this.Font);
PointF textPoint = new PointF((ClientRectangle.Width - textSize.Width) / 2, (ClientRectangle.Height - textSize.Height) / 2);
e.Graphics.DrawString(hit, this.Font, Brushes.Yellow, textPoint);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (ControlHit != null)
ControlHit(this, new EventArgs());
}
public void SubscribeToOtherClick(Poly p)
{
p.ControlHit += new EventHandler(OtherControlClicked);
}
private void OtherControlClicked(object sender, EventArgs e)
{
_hitPoint++;
Refresh();
}
private int _hitPoint;
}
static void Main(string[] args)
{
Form f = new Form();
f.Size = new Size(500, 500);
Poly poly1 = new Poly();
poly1.Left = 10;
poly1.Top = 10;
poly1.Width = (f.ClientRectangle.Width - 40) / 2;
poly1.Height = f.ClientRectangle.Height - 20;
poly1.Anchor = AnchorStyles.None;
Poly poly2 = new Poly();
poly2.Left = poly1.Right + 20;
poly2.Top = 10;
poly2.Width = (f.ClientRectangle.Width - 40) / 2;
poly2.Height = f.ClientRectangle.Height - 20;
poly2.Anchor = AnchorStyles.None;
poly1.SubscribeToOtherClick(poly2);
poly2.SubscribeToOtherClick(poly1);
f.Controls.Add(poly1);
f.Controls.Add(poly2);
f.ShowDialog();
}
}