The button requires two clicks to fire up the event. Here is an image and the code.There is a combobox which triggers the button with different items, but when I click the button to show an item in a panel on the page, I have to click it twice so it can trigger the event. After selecting an item once by twice-clicking it, every next time i click it works with one click, just like it should.
Here is the image of the combobox which triggers the button
And there is the code :
namespace Carbon
{
public partial class ucAnaliza : MetroFramework.Controls.MetroUserControl
{
static ucAnaliza _instance;
public static ucAnaliza Instance3
{
get
{
if (_instance == null)
_instance = new ucAnaliza();
return _instance;
}
}
public MetroFramework.Controls.MetroPanel MetroAnaliza
{
get { return mPanelAnaliza; }
set { mPanelAnaliza = value; }
}
public ucAnaliza()
{
InitializeComponent();
}
private void ucAnaliza_Load(object sender, EventArgs e)
{
}
private void mPotvrdiElementi_Click(object sender, EventArgs e)
{
switch (((ComboBox)mDropAnaliza).SelectedItem.ToString())
{
case "Главна рамка":
_instance = this;
ucGlavna uc = new ucGlavna();
uc.Dock = DockStyle.Bottom;
mPanelAnaliza.Controls.Add(uc);
break;
case "Челна рамка":
_instance = this;
ucCelna uc2 = new ucCelna();
uc2.Dock = DockStyle.Bottom;
mPanelAnaliza.Controls.Add(uc2);
break;
case "Подолжна рамка":
_instance = this;
ucPodolzna uc3 = new ucPodolzna();
uc3.Dock = DockStyle.Bottom;
mPanelAnaliza.Controls.Add(uc3);
break;
}
}
}
}
Here is the code from the designer for the button :
// mPotvrdiElementi
//
this.mPotvrdiElementi.BackColor = System.Drawing.Color.Transparent;
this.mPotvrdiElementi.CausesValidation = false;
this.mPotvrdiElementi.Cursor = System.Windows.Forms.Cursors.Hand;
this.mPotvrdiElementi.ForeColor = System.Drawing.SystemColors.MenuBar;
this.mPotvrdiElementi.Image = global::Carbon.Properties.Resources.Checked_Checkbox_24px;
this.mPotvrdiElementi.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
this.mPotvrdiElementi.ImageSize = 24;
this.mPotvrdiElementi.Location = new System.Drawing.Point(758, 34);
this.mPotvrdiElementi.Name = "mPotvrdiElementi";
this.mPotvrdiElementi.Size = new System.Drawing.Size(80, 25);
this.mPotvrdiElementi.Style = MetroFramework.MetroColorStyle.Orange;
this.mPotvrdiElementi.TabIndex = 4;
this.mPotvrdiElementi.TabStop = false;
this.mPotvrdiElementi.Text = "Потврди";
this.mPotvrdiElementi.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.mPotvrdiElementi.UseCustomBackColor = true;
this.mPotvrdiElementi.UseCustomForeColor = true;
this.mPotvrdiElementi.UseSelectable = true;
this.mPotvrdiElementi.UseStyleColors = true;
this.mPotvrdiElementi.Click += new System.EventHandler(this.mPotvrdiElementi_Click);
I know it is a long time ago but I was having the same problem...
But I found a solution to the problem and is working every time and not killing the usability.
private int focusFlag = 0;
private void MainForm_MouseEnter(object sender, EventArgs e)
{
if (focusFlag < 1)
{
this.FocusMe();
++focusFlag;
}
}
This will not always try to focus on that form when trying to go to other forms or something else, it will just focus once and that is enough... after that it will behave normally :)
It seems the MetroForm doesn´t get Focus until you click within the form and it is just a bug from the developers of the MetroFramework when using certain Metro Controls within the Form.
I have seen others posting the same problem when they are using the MetroFramework.
Hopefully this will help.
Related
The problem I'm having is where I can successfully use the RoomID of the Room object I've created, but not the panel. Here is the function where I set the label to the name of the room. (This is my Form1.cs)
public partial class Form1 : Form
{
Room ThisRoom = new Room();
public Form1()
{
InitializeComponent();
this.Text = "Aquinas College Master Controller";
}
private void roomDesignerToolStripMenuItem_Click(object sender, EventArgs e)
{
new RoomDesigner().Show();
}
private void button1_Click(object sender, EventArgs e)
{
roomsToolStripMenuItem.DropDownItems.Clear();
foreach (var Room in Global.Aquinas.Aquinas)
{
ToolStripMenuItem NewItem = new ToolStripMenuItem(Room.RoomID);
NewItem.Name = Room.RoomID;
NewItem.Click += new EventHandler(ItemClick);
roomsToolStripMenuItem.DropDownItems.Add(NewItem);
}
}
void ItemClick(object sender, EventArgs e)
{
ToolStripItem item = (ToolStripItem)sender;
label2.Text = item.Name;
foreach (var Room in Global.Aquinas.Aquinas)
{
if (Room.RoomID == item.Name)
{
ThisRoom = Room;
break;
}
}
Panel RoomPanel = ThisRoom.Panel;
RoomPanel.Size = new Size(607, 304);
RoomPanel.Location = new Point(144, 27);
RoomPanel.BackColor = Color.White;
this.Controls.Add(RoomPanel);
}
}
This is some of my code for the room object. (This is in Room.cs)
public class Room
{
private List<CtrlComputer> _Computers;
public List<CtrlComputer> Computers
{
get { return _Computers; }
set { _Computers = value; }
}
private string _RoomID;
public Room()
{
_Computers=new List<CtrlComputer>();
}
public string RoomID
{
get
{
return _RoomID;
}
set
{
_RoomID = value;
}
}
public Panel Panel
{
get
{
return _Panel;
}
set
{
_Panel = value;
}
}
private Panel _Panel;
}
And here is where I register the panel which I have just put my designs on, to a new room. (This is some of my RoomDesigner.cs)
public partial class RoomDesigner : Form
{
Room NewRoom = new Room();
Panel RoomDesignerPanel = new Panel();
public RoomDesigner()
{
InitializeComponent();
RoomDesignerPanel.Size = new Size(607, 304);
RoomDesignerPanel.Location = new Point(144, 27);
RoomDesignerPanel.BackColor = Color.White;
this.Controls.Add(RoomDesignerPanel);
textBox1.ForeColor = SystemColors.GrayText;
textBox1.Text = "Enter Computer ID Here";
this.textBox1.Leave += new System.EventHandler(this.textBox1_Leave);
this.textBox1.Enter += new System.EventHandler(this.textBox1_Enter);
textBox2.ForeColor = SystemColors.GrayText;
textBox2.Text = "Enter Room ID Here";
this.textBox2.Leave += new System.EventHandler(this.textBox2_Leave);
this.textBox2.Enter += new System.EventHandler(this.textBox2_Enter);
}
private void textBox1_Leave(object sender, EventArgs e)
{
if (textBox1.Text.Length == 0)
{
textBox1.Text = "Enter Computer ID Here";
textBox1.ForeColor = SystemColors.GrayText;
}
}
private void textBox1_Enter(object sender, EventArgs e)
{
if (textBox1.Text == "Enter Computer ID Here")
{
textBox1.Text = "";
textBox1.ForeColor = SystemColors.WindowText;
}
}
private void textBox2_Leave(object sender, EventArgs e)
{
if (textBox2.Text.Length == 0)
{
textBox2.Text = "Enter Room ID Here";
textBox2.ForeColor = SystemColors.GrayText;
}
}
private void textBox2_Enter(object sender, EventArgs e)
{
if (textBox2.Text == "Enter Room ID Here")
{
textBox2.Text = "";
textBox2.ForeColor = SystemColors.WindowText;
}
}
private void button1_Click(object sender, EventArgs e)
{
CtrlComputer NewComputer = new CtrlComputer();
NewComputer.ComputerID = textBox1.Text;
NewComputer.Text = NewComputer.ComputerID;
NewComputer.Parent = RoomDesignerPanel;
RoomDesignerPanel.Controls.Add(NewComputer);
NewRoom.Panel = RoomDesignerPanel;
NewRoom.Add(NewComputer);
}
When I try to reload that panel, the RoomID of that object is returned fine, yet the panel is not. Any ideas?
Edit: Sorry for the lack of clarity in my post, first posts aren't always easy.
The panel is created in the designer, but I tried private Panel Panel1 = new Panel(); with no luck. My current problem is that in Form1.cs, the program will throw "Cannot access a disposed object", but I followed the guide here https://msdn.microsoft.com/en-us/library/82785s1h(v=vs.110).aspx .
What you are looking to do is swap between a collection of Panel objects (kind of like your own version of TabPages). To do this you need to create each of the Panel objects (You do this in RoomDesigner, which is fine, but there is a catch: see * below). With that collection in hand, when you want to show it on the form, you need to remove the panel1 the designer code created (Controls.Remove(panel1)) and insert your new one (Controls.Add(RoomPanel)).
Since Controls utilize system resources, make sure to Dispose any control you will no longer use. Here is an example method:
//Initial case where no room has been displayed yet and panel1 is still valid
private Panel CurrentPanel = null;
public void SwapPanel(Panel p)
{
//If no panel has been placed yet, get rid of the default one
if (panel1 != null)
{
//we should never need the designer panel again, so dispose it
panel1.Dispose();
this.Controls.Remove(panel1);
}
else
{
//we may return to this panel later, so don't dispose it
this.Controls.Remove(CurrentPanel);
}
CurrentPanel = p;
this.Controls.Add(p);
}
When you finally close out and no longer need your Panels stored in your Room collection, make sure to Dispose them. (However, if your whole program is exiting at that point then it doesn't matter, but do it anyway as good practice)
*When you close any RoomDesigner form (or any form), all controls it contains in 'Controls' will be disposed, even if you are using them elsewhere. To prevent this, remove the controls you want to preserve from the RoomDesigner Controls collection before it is closed.
I have a button that opens a Window.
If the button is pressed again, it opens a duplicate of the same window.
info = new Info();
info.Owner = Window.GetWindow(this);
info.Show();
How do you check if the Window is already open, and deny a duplicate from being opened again?
I can't use info.ShowDialog() because it disables the Main Window.
Solutions that have not worked:
Info info = new Info();
if (!info.IsActive)
{
info = new Info();
info.Owner = Window.GetWindow(this);
info.Show();
}
Info info = new Info();
if (info.Visibility != Visibility.Visible)
{
info.Owner = Window.GetWindow(this);
info.Show();
}
public static bool IsWindowOpen<T>(string name = "") where T : Window
{
return string.IsNullOrEmpty(name)
? Application.Current.Windows.OfType<T>().Any()
: Application.Current.Windows.OfType<T>().Any(w => w.Name.Equals(name));
}
private void buttonInfo_Click(object sender, RoutedEventArgs e)
{
if (!IsWindowOpen<Window>("Info"))
{
Info info = new Info();
info.Owner = Window.GetWindow(this);
info.Show();
}
}
Create a form only when value is not null.
If the form was closed put the value back to null with the FormClosed event.
public static Info info;
if(info == null){
info = new Info();
info.Show();
}
put an event form close on the info form
private void info_FormClosed(object sender, FormClosedEventArgs e)
{
MainForm1.info = null;
}
It works for me
The sensible approach is to just keep track of the Window instance so you don't have to find it back later. Add a field:
private Info infoWindow;
If it is null then you know that the window doesn't exist yet, so you'll want to create it. Use the Closed event to set the variable back to null. If it is not null then you want to make sure that the window gets restored. So:
private void button_Click(object sender, RoutedEventArgs e) {
if (infoWindow == null) {
infoWindow = new Info();
infoWindow.Closed += (s, ea) => infoWindow = null;
infoWindow.Owner = this; // optional
infoWindow.Show();
}
else {
if (infoWindow.WindowState == WindowState.Minimized) {
infoWindow.WindowState = WindowState.Normal;
}
infoWindow.Activate();
}
}
And you probably also want to close the window automatically when the window that contains the button is closed:
private void Window_Closed(object sender, EventArgs e) {
if (infoWindow != null) infoWindow.Close();
}
You could use .IsLoaded field or bind the .ContentRendered event
Edit 1 -
Window1:
public class Window1 : Window
{
private Info info = null;
private Boolean IsInfoOpened = false;
protected void OpenInfo()
{
if (this.IsInfoOpened) return;
this.info = new Info();
this.info.ContentRendered += delegate { this.IsInfoOpened = true; };
this.info.Closed += delegate { this.IsInfoOpened = false; }
this.info.Show();
}
}
Can I create a button with both .Image and .Text properties simultaniously, in such way, that text is not visible on form, and is created just for identifying what button should do at the moment?
Using TextAlign and TextImageRelation properties doesn't help. Text is always visible, just a position changes.
private System.Windows.Forms.Button bRenameCourse;
this.bRenameCourse.BackColor = System.Drawing.SystemColors.ButtonFace;
this.bRenameCourse.Image = ((System.Drawing.Image)(resources.GetObject("bRenameCourse.Image")));
this.bRenameCourse.Location = new System.Drawing.Point(966, 6);
this.bRenameCourse.Name = "bRenameCourse";
I want this text "Rename" to be not visible on button
this.bRenameCourse.Text = "Rename";
this.bRenameCourse.Size = new System.Drawing.Size(64, 60);
this.bRenameCourse.TabIndex = 10;
this.bRenameCourse.UseVisualStyleBackColor = false;
this.bRenameCourse.Click += new System.EventHandler(this.bRenameCourse_Click);
Here is why do I want it works :
private void bRenameCourse_Click(object sender, EventArgs e)
{
if (bRenameCourse.Text.Equals("Rename"))
{
//DO SMTHNG
bRenameCourse.Text = "OK";
}
else if (bRenameCourse.Text.Equals("OK"))
{
//DO SMTHNG
bRenameCourse.Text = "Rename";
}
}
I can avoid this using some flags, but I'd like to know if it's possible in general.
Don't use the .Text property of the button to store information.You can use the .Tag property
ie
this.bRenameCourse.Tag = "Rename";
And in the Event
private void bRenameCourse_Click(object sender, EventArgs e)
{
if (bRenameCourse.Tag.Equals("Rename"))
{
//DO SMTHNG
bRenameCourse.Tag = "OK";
}
else if (bRenameCourse.Tag.Equals("OK"))
{
//DO SMTHNG
bRenameCourse.Tag = "Rename";
}
}
Just set the .Text property to ""(blank or empty)
I'm currently working in VS 2012.
.NET 4.5 and working on an mmc snap-in. (i know right?!)
so i followed this topic:
Is there a simple way to implement a Checked Combobox in WinForms
as i want something similar to the scheduled task manager.
But that solution does not seem to work for me.
the listview pops up but when i try to click on a checkbox in my listview.
It gives me a big middle finger and closes my dropdown.
is there any way i can suppress the combobox's "focus lost" close event?
i can, not hide the list but then it never hides.
For Example:
// designer class
//
// comboBox1
//
this.comboBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.comboBox1.DropDownHeight = 1;
this.comboBox1.DropDownWidth = 1;
this.comboBox1.FormattingEnabled = true;
this.comboBox1.IntegralHeight = false;
this.comboBox1.Location = new System.Drawing.Point(256, 371);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(238, 21);
this.comboBox1.TabIndex = 5;
this.comboBox1.DropDown += new System.EventHandler(this.comboBox1_DropDown);
this.comboBox1.DropDownClosed += new System.EventHandler(this.comboBox1_DropDownClosed);
//
// lstWeekDays
//
this.lstWeekDays.CheckBoxes = true;
this.lstWeekDays.Location = new System.Drawing.Point(50, 63);
this.lstWeekDays.Name = "lstWeekDays";
this.lstWeekDays.Size = new System.Drawing.Size(263, 97);
this.lstWeekDays.TabIndex = 13;
this.lstWeekDays.Tag = "lstlstWeekDays";
this.lstWeekDays.UseCompatibleStateImageBehavior = false;
this.lstWeekDays.View = System.Windows.Forms.View.SmallIcon;
this.lstWeekDays.Visible = false;
// Code behind
public Form1()
{
InitializeComponent();
this.lstWeekDays.Items.Add("Monday");
this.lstWeekDays.Items.Add("Tuesday");
this.lstWeekDays.Items.Add("Wednesday");
this.lstWeekDays.Items.Add("Thursday");
this.lstWeekDays.Items.Add("Friday");
this.lstWeekDays.Items.Add("Saturday");
this.lstWeekDays.Items.Add("Sunday");
}
private void comboBox1_DropDown(object sender, EventArgs e)
{
lstWeekDays.Visible = true;
}
private void comboBox1_DropDownClosed(object sender, EventArgs e)
{
lstWeekDays.Visible = false;
}
Add the checkboxes to this list instead of the panel.
I am dynamically assigning forms to tab pages. It works fine, except when I try to assign
an updated version of the form (with different text values assigned to the controls) to the tab page. I am actually a little surprised that it doesn't crash when I create multiple instances of the form and assign them to the tab page (if the new ones are just stacking on top of the older ones, you would think the new one would be on top and the new values are visible).
So...what do I need to do to remove the previous form I added to the tab page before adding the new version? Or can I access the existing form and change its values.
I guess it would be clearer if I just showed the code:
Main form:
private enum TabControls {
BasicInfo,
ConfidentialInfo,
RolesAndSecurity,
InactiveInfo
}
string currentNode = string.Empty;
public Form1() {
InitializeComponent();
CenterToScreen();
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) {
currentNode = e.Node.Name;
UpdateActiveTabForNode();
}
// This is called both by treeView1_AfterSelect (sic, I changed the name to
// treeViewSearchWorker) and by tabControlWorker_SelectedIndexChanged().
// currentNode is set/overwritten on clicking a node and saved in a form var.
// The active tab page is always known via the TabControl's SelectedIndex
// property, so there is no need to pass in either value.
private void UpdateActiveTabForNode() {
int ActiveTabPage = tabControlWorker.SelectedIndex;
switch (ActiveTabPage) {
case (int)TabControls.BasicInfo:
if (tabPageBasicInfo.Controls.Count > 0) {
;// tabPageBasicInfo.Controls.Remove(0);<-- What to pass in here?
}
BasicInfoPseudoTab bipt = new BasicInfoPseudoTab(currentNode);
tabPageBasicInfo.Controls.Add(bipt);
tabPageBasicInfo.BringToFront();
bipt.Show();
break;
case (int)TabControls.ConfidentialInfo:
ConfidentialInfoPseudoTab cipt = new ConfidentialInfoPseudoTab(currentNode);
tabPageConfidentialInfo.Controls.Add(cipt);
cipt.Show();
break;
case (int)TabControls.RolesAndSecurity:
RolesAndSecurityPseudotab raspt = new RolesAndSecurityPseudotab(currentNode);
tabPageRolesAndSecurity.Controls.Add(raspt);
raspt.Show();
break;
case (int)TabControls.InactiveInfo:
InactiveInformationPseudoTab iipt = new InactiveInformationPseudoTab(currentNode);
tabPageInactiveInfo.Controls.Add(iipt);
iipt.Show();
break;
default: {
break;
// TODO: Do something?
}
}
}
private void tabControlWorker_SelectedIndexChanged(object sender, System.EventArgs e) {
UpdateActiveTabForNode();
}
}
====
Form that serves as one of the pseudo tabPages:
public partial class BasicInfoPseudoTab : Form {
String _aNodeName = String.Empty;
public BasicInfoPseudoTab(String ANodeName) {
InitializeComponent();
// Without this, you get "TopLevel control cannot be added to a control"
this.TopLevel = false;
this.FormBorderStyle = FormBorderStyle.None;
this.Visible = true;
this.Dock = DockStyle.Fill;
_aNodeName = ANodeName;
SetDisplayVals();
}
private void SetDisplayVals() {
if (_aNodeName == "NodeBuckingham") {
textBoxFirstName.Text = "Buckingham";
textBoxLastName.Text = "Piranha";
textBoxNickname.Text = "B.P.";
}
else if (_aNodeName == "NodeVolcano") {
textBoxFirstName.Text = "Volcano";
textBoxLastName.Text = "Jerry";
textBoxNickname.Text = "V.J.";
} else if (_aNodeName == "NodeParsons") {
textBoxFirstName.Text = "Parsons";
textBoxLastName.Text = "Spalding";
textBoxNickname.Text = "P.S.";
} else {
textBoxFirstName.Text = String.Empty;
textBoxLastName.Text = String.Empty;
textBoxNickname.Text = String.Empty;
}
}
Updated:
I got it working by declaring the form variables outside the event handler and disposing them if they were not null before proceeding.
string currentNode = string.Empty;
BasicInfoPseudoTab bipt;
ConfidentialInfoPseudoTab cipt;
RolesAndSecurityPseudotab raspt;
InactiveInformationPseudoTab iipt;
. . .
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) {
currentNode = e.Node.Name;
UpdateActiveTabForNode();
}
private void UpdateActiveTabForNode() {
int ActiveTabPage = tabControlWorker.SelectedIndex;
switch (ActiveTabPage) {
case (int)TabControls.BasicInfo:
if (null != bipt) {
bipt.Dispose();
}
bipt = new BasicInfoPseudoTab(currentNode);
tabPageBasicInfo.Controls.Add(bipt);
bipt.Show();
break;
. . .
As you wish, use module level variables, one for each form, if null, new it, else as above. If you are creating forms constantly on top of each other how are you ever going to clean up? Check the size of your working set as you keep creating forms.