Trigger dialog buttons on IWebMatrixHost ShowDialog method - c#

I have created a custom XAML UserControl class that I pass to the ShowDialog method. I would like to be able to trigger clicking the OK button on the dialog through other events generated in my UserControl - for example double clicking a ListItem. I have the code to handle the double click just fine (tied into the MouseDown even and checked the click count) but I don't know how to trigger a new event to the parent dialog to close it.
// Bound to TextBlock, part of a ListBox on a UserControl
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
// trigger dialog to close with OK button
}
}

Make your user control implement IDialogContent. You can then call directly to the CloseDialog event you implemented, and that will trigger the dialog closure.
You will need to decide how you want to handle that in your follow up code by setting some sort of state on your user control/view model or some other data as fits your particular extension.
// Bound to TextBlock, part of a ListBox on a UserControl
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
CloseDialog(this, EventArgs.Empty);
}
}

Related

How do I set focus to a Usercontrol

I have 50 UserControls that I add to a flowlayoutPanel dynamically.
I need to set focus to a user control but it doesn't work.
I have been searching a lot but can't find any example that I understand.
The only example that I find is this
Setting Focus to a .NET UserControl...?
I tried to use userCtrl.Focus(); but it didn't work.
As I have been reading the usercontrol doesn't like to have focus.
Addition: Now that I understand more of the Control class, I
understand that if you derive from Control you should not subscribe
to its events, but use the On.. functions, like OnEnter. I've
changed my answer accordingly
To Activate any Control, including a UserControl use Control.Select().
If you do this for a TextBox, you'll see that Select ensures that it gets the input focus.
I guess you want to do something with the selected UserControl (the Control that has the focus), for instance, you want to change its appearance, or select any of the controls on it. To do this, your UserControl class has to subscribe to the events Control.Enter and Control.Leave
I have created a UserControl with a CheckBox that is automatically checked whenever the UserControl is selected (has the input focus):
Addition: If you derive from a Control, don't subscribe to events Enter and Leave. Instead override the functions that raise these events: OnEnter / OnLeave.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
protected override void OnEnter(EventArgs e)
{
this.checkBox1.Checked = true;
base.OnEnter(e); // this will raise the Enter event
}
protected override void OnLeave(EventArgs e)
{
this.checkBox1.Checked = false;
base.OnLeave(e); // this will raise the Leave event
}
}
I have a form with a button, and an event handler that is called when the button is clicked:
private void OnButton1Clicked(object sender, EventArgs e)
{
this.userControl1.Select();
}
Now whenever the button is clicked I see that the user control gets the focus because the check box is checked and whenever I click elsewhere the checkbox is unchecked.
You can set focus to a control by using the ActiveControl Property
this.ActiveControl = myUserControl;
Though you did not detail what did you mean it did not work, focusing has many aspects conventionally.
1. Explicit focusing
Calling Focus() method of a control is the same as setting ActiveControl of the container form. If CanFocus returns true (your control and all its parents are visible and enabled), it works; however, you will have no visual feedback, except some indirect hint, eg. the originally focused control (button or textbox) loses the focus.
To visualize the focused state you might want to use some custom paint:
protected override void OnPaintBackground(PaintEventArgs e)
{
e.Graphics.Clear(Focused ? SystemColors.Highlight : SystemColors.Control);
}
If you derive directly from Control instead of UserControl, override the following two methods to force a repaint on changing the focused state:
protected override void OnGotFocus(EventArgs e)
{
Invalidate();
base.OnGotFocus(e);
}
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
Invalidate();
}
2. Focusing by the mouse
To receive focus by clicking the control add this line to the constructor:
SetStyle(ControlStyles.Selectable, true);
If you derive directly from Control instead of UserControl, override the OnMouseDown, too:
protected override void OnMouseDown(MouseEventArgs e)
{
if (!Focused)
Focus();
base.OnMouseDown(e);
}
3. Focusing by the keyboard
To receive focus by the TAB key just set the TabStop property to true and adjust the TabOrder property.
Example to focus on textBox1:
textBox1.Select();
you can try tab index of the user control. If you set its tab index to 1 it will be focused once the program start.

Windows Forms click event not fired when clicking on label?

I have Windows Form TestForm, and in my Form I have several labels that are only used to display some text.
I need to display a MessageBox.Show anytime the Form is clicked. So I have an event handler for the click, which looks like this:
private void TestForm_Click(object sender, EventArgs e)
{
MessageBox.Show("The form has been clicked");
}
Unfortunately, the click event doesn't fire when I click over a label in the Form. Is there a way to fix this, besides consuming the click event for the labels?
Thanks.
To use the same click event for all labels:
In the properties for each label, go to the Events (lightning bolt tab).
You will see (probably near the top) a label for Click, click the dropdown for this event, and you will be shown a list of handlers that you could use for that label.
Here's the Properties > Events > Click handler (bottom right):
Because all of your labels are of the same type, and produce the same EventArgs, you are able to use the same handler for all of them.
Then, when you are adding more Labels, just choose the event handler from the Click event dropdown:
Hope this helps!
To flesh out LarsTech's comment, I have used something like this in the past when I was having problems with labels overlapping each other and lack of true transparency in WinForms. What I did was make the labels invisible on the Form, then iterate through them in the Form's paint event, pull the information out of them and then use Graphics.DrawString to draw the text. That way you you will still be able see them in design mode.
This is a quick example of what I mean.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (var temp in this.Controls)
{
if (temp is Label) //Verify that control is a label
{
Label lbl =(Label)temp;
e.Graphics.DrawString(lbl.Text, lbl.Font, new SolidBrush(lbl.ForeColor), new Rectangle(lbl.Location, lbl.Size));
}
}
}
private void Form1_Click(object sender, EventArgs e)
{
MessageBox.Show("The Form has been clicked");
}
}

Update listBox on Main page from button click event on child window.

I have a Main page that contains a listBox.
When a user selects a profile form the list box, this opens up a child window called pWindow.
This window as the option to delete the current profile via a hyperlink button that opens up a another confirmation window called dprofile.
My question being is it possible that once a user has confirmed to delete the current profile they are in, and confirmed it in the button click on dProfile, how can I update the listBox in the first Main page so that the list no longer contains the deleted profile (which it is not doing at present.
In the dProfile window I have created an event -
public event EventHandler SubmitClicked;
Where in the OK button click I have-
private void OKButton_Click(object sender, RoutedEventArgs e)
{
if (SubmitClicked != null)
{
SubmitClicked(this, new EventArgs());
}
}
So on the Main page I have added-
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
WebService.Service1SoapClient client = new WebService.Service1SoapClient();
listBox1.Items.Clear();
client.profileListCompleted += new EventHandler<profileListCompletedEventArgs>(client_profileListCompleted);
client.profileListAsync(ID);
}
I thought this may have updated the listBox as it was confirmed in the dProfile form however when the form closes, the listBox stays the same and I have to manually refresh the webpage to see the update. How can I do this?
If I understood it correctly then you have three pages. Main, pWindow and dProfile. Earlier you were trying to close pWindwow from dProfile and that was working properly. Now you want to refresh the listBox1 on Main Page.
To achieve that you may follow a similar strategy. You are probably opening pWindow from Main page with something on the following line
pWindow pWin = new pWindow();
pWin.Show();
Now you may define a new event in pWindow class.
public event EventHandler pWindowRefeshListBox;
Then in your event handler for deleteProfile_SubmitClicked you may raise the event to refresh listbox1, something on the following line:
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
if(pWindowRefreshListBox != null)
pWindowRefreshListBox(this, new EventArgs());
this.Close();
}
Then in your main page register the event against pWin object, which you defined earlier.
pWin.pWindowRefreshListBox += new new EventHandler(pWindow_pWindowRefreshListBox);
Then define the event in Main page.
private void pWindow_pWindowRefreshListBox(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
This should refresh the listbox. I haven't test the code or the syntax. So you may check it
before implementing.
EDIT
you may define the event in dProfile as static
public static event EventHandler SubmitClicked;
Then you will be able to register it in Main and pWindow against Class Name
dProfile.SubmitClicked += new ..............
Then implement it accordingly, in pWindow, close the window and in main refresh listbox
EDIT:
You may create instance of deleteProfile on the main page register the following in your main
deleteProfile.SubmitClicked += new EventHandler(deleteProfile _SubmitClicked)
this should work

How to Call an Event of Control that is present inside a Custom Control?

I have a Custom Cntrol that has a button inside it. Now I want to access the button click from my Application Page.
Take a look at this Post:
How to Access a Button present inside a Custom Control, from the implementing page?
You have 2 ways:
You can access the button's click event through the user control object. For eg.
MyUC.button1.click += //etc
You can create your custom event of that specific button click in the user control. For example, in your usercontrol, you have:
public delegate void OnButtonClick(object sender, EventArgs e);
public event OnButtonClick Button1Click;
button1_click(object sender, EventArgs e)
{
if(Button1Click != null)
Button1Click(this, e);
}
Then you watch for that event on your user control:
MyUC.Button1Click += //etc.

How to handle Copy for multiple controls when adding a ShortcutKey to menu item?

If I do not create an "Edit->Copy" menu item and assign it the shortcut keys "CTRL+C", then I can select a control (RichTextBox, DataGridView, etc..) and hit "CTRL+C" and the control itself will handle the copy. I can copy text out, and paste it into notepad, etc..
Now throughout my whole form, I have a lot of controls. But I have a custom control that I want to make clear that I handle Copy functionality for. So I added the ShortcutKey CTRL+C to Edit->Copy, and by default it is set to Enabled.
Now, I have to implement an event handler for the 'click' event on that menu item. If I explicitly put in code to handle the copy, then it works:
public void menuEditCopy_Click(object sender, EventArgs e)
{
myCustomControl.Copy();
}
However, now Copy does not work on any other type of control. My first inclination was to find out the type of control that has focus, and implement a limited set of copy code for each of them:
public void menuEditCopy_Click(object sender, EventArgs e)
{
if (this.ActiveControl is MyCustomControl)
{
((MyCustomControl)this.ActiveControl).Copy();
}
else if (this.ActiveControl is RichTextBox)
{
((RichTextBox)this.ActiveControl).Copy();
}
}
etc...
However, my controls are added to a SplitContainer, and debugging shows that this.ActiveControl is set to the splitcontainer instance, not the control, even though I know that control is selected.
So my last thought is to literally check if every control has focus:
public void menuEditCopy_Click(object sender, EventArgs e)
{
if (myCustomControl.Focused)
{
myCustomControl.Copy();
}
else if (richTextBox1.Focused)
{
richTextBox1.Copy();
}
}
I would like to avoid this if possible, it is a lot of controls, and if I add a new control, I would need to update it. Is there a better way of doing this?
Thanks
A SplitContainer implements ContainerControl, so you could check for either one and look for it's ActiveControl instead. ContainerControl is the base class, so I would go for that - you might catch another type of container as well:
private void DoCopy(Control control)
{
if(control is ContainerControl)
DoCopy(control.SelectedControl);
else if(control is MyCustomControl)
((MyCustomControl)control).Copy();
else if(control is RichTextBox)
((RichTextBox)control).Copy();
else
throw new NotSupportedException("The selected control can't copy!");
}
void menuEditCopy_Click(object sender, EventArgs e)
{
DoCopy(this.ActiveControl);
}
You could try settting the KeyPreview property of your form to true. Then you could set up a handler for the form's KeyDown event which would look like the following:
private void Form_KeyDown(object sender, KeyEventArgs e)
{
if(e.Modifiers == Keys.Control && e.KeyCode == Keys.C)
{
if (ActiveControl.GetType() == typeof(MyCustomControl))
{
((MyCustomControl)ActiveControl).Copy();
e.Handled = true;
}
}
}
Here you are specifying that you have handled the Ctrl-C event by setting the event args Handled property to true. Else, if you leave it as false, the Ctrl-C key press will be handled as per usual by each individual control.
Because we have set the KeyPreview to true the form's handler gets to see each key press before any other control that it contains and can decide to deal with the key press itself or else allow it to be handled in the same way as if the form had never previewed it.
I think as well it would be necessary to remove the short-cut key from your menu item (although you could still manually put the text "Ctrl+C" next to your menu item name) for this to work, otherwise your menu item will hijack the key stroke.

Categories