Grey out winform app except open dialog - c#

I would like to "grey out" my winform app all except the currently open dialog, is this possible?

You should use ShowDialog() instead of Show(). That will disable all other windows except for the new one.
To "grey out" visually you will have to set form.Enabled=false; manually and revert it once the dialog is closed (which is not too hard since ShowDialog() is a blocking call).

A little twisty but it seem to simulate the "grey out" feeling. You need to use the form deactivate event and the form activate event. You can make every of your forms inherits from this class. It didn't seem to hurt the performance.
public class GrayingOutForm : Form
{
public GrayingOutForm()
{
this.Activated += this.Form1_Activated;
this.Deactivate += this.Form1_Deactivate;
}
private readonly List<Control> _controlsToReEnable = new List<Control>() ;
private void Form1_Activated(object sender, EventArgs e)
{
foreach (var control in _controlsToReEnable)
control.Enabled = true;
}
private void Form1_Deactivate(object sender, EventArgs e)
{
_controlsToReEnable.Clear();
foreach (var control in this.Controls)
{
var titi = control as Control;
if (titi != null && titi.Enabled)
{
titi.Enabled = false;//Disable every controls that are enabled
_controlsToReEnable.Add(titi); //Add it to the list to reEnable it after
}
}
}
}
Now you can move freely between yours windows and every window seem to desactivate.

Related

All buttons state change in C# [duplicate]

This question already has answers here:
How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?
(28 answers)
Closed 2 years ago.
What I am trying to do is to change background color of the button once it's active. So far I achieved it by this way:
private void button3_Click(object sender, EventArgs e) // METEO BUTTON
{
DefaultButtons();
button3.BackColor = Color.LimeGreen;
// REST OF THE CODE HOES HERE
}
While DefaultButtons function is like this:
public void DefaultButtons()
{
List<Button> buttonsToDefualt = new List<Button>()
{
// MAIN MENU
button1,
button2,
[...]
buttonX
};
foreach (var item in buttonsToDefualt)
{
item.BackColor = Color.Green;
}
}
Now swapping buttons works like this: Change entire list to default color, then activated button change color to LimeGreen. It would be fine but:
1) I have to launch DefaultButtons(); for EACH button Click
2) I have to manually add all buttons to list, and now I have more than 120 buttons (Yeah, building custom interface...), and keep adding that by hand is tiring.
I tried this:
void DefaultButtonsNew()
{
foreach (Button b in this.Controls)
{
if (b != null)
{
b.BackColor = Color.Green;
}
}
}
But I've got an Exception: System.InvalidCastException: 'Can't throw object 'System.Windows.Forms.SplitContainer' on type 'System.Windows.Forms.Button'.'
If you're looking for a way to reset all buttons on the form, and some buttons are inside other containers, then we need to recursively loop through each control's Controls collection to find all the buttons.
One easy way to do that is to write a method that takes in a container (like the form), iterates through its Controls collection, changes the BackColor of any Button controls, and calls itself for the other control types:
private void ResetButtons(Control container)
{
// Loop through each control in this container
foreach (Control control in container.Controls)
{
var button = control as Button;
// If the control is a button, change it's backcolor
if (button != null) button.BackColor = Color.Green;
// Otherwise check it's controls collection (recursive call)
else ResetButtons(control);
}
}
Next, it sounds like you're looking for a way to avoid writing out a call to this method, and to change the BackColor of the current button, in every button click event.
One easy way around this is to simply add this method, and the BackColor change, to every button click in code. We can write a method to do this using a similar pattern - loop through every control in every container, and if it's a button, add a method to it's click event:
private void HookupButtonClickEvent(Control container)
{
// Loop through each control in this container
foreach (Control control in container.Controls)
{
var button = control as Button;
// If the control is a button, add a method to it's click event
if (button != null)
{
button.Click += (s, e) =>
{
ResetButtons(container);
button.BackColor = Color.LimeGreen; // Change this button's color
};
}
// Otherwise check it's controls collection (recursive call)
else HookupButtonClickEvent(control);
}
}
Now, all we have to do is call the ResetButtons and HookupButtonClickEvent in our form's constructor, and every button will start with the same backcolor and will have our reset method call in it's click event:
public Form1()
{
InitializeComponent();
HookupButtonClickEvent(this);
ResetButtons(this);
}
Note that this does not prevent you from adding additional click events to the buttons. It merely provides a way to hook up the common functionality to all buttons without writing a bunch of duplicated code.
You can still double-click the controls on your form to add other Click event handlers:
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Button one clicked - doing something unique here");
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("Button two clicked - doing something else here");
}
The iterator on Controls collection returns all the controls and trying to cast it to Button should an do fail.
Change your method like this:
void DefaultButtonsNew()
{
foreach (Control b in this.Controls)
{
if (b is Button)
{
b.BackColor = Color.Green;
}
}
}

Pop-up window in a WPF application

I've a C# WPF application which show uses Grid control in the xaml(P screen).For every row in the grid, I've a column called Details.Clicking on item in this column shows a pop-up windows which also has a grid in the xaml(C screen).
My item click event in the P's viewmodel has the following code:
var myChildWindow = new MyGridView();
myChildWindow.Show();
If the user clicks on the item multiple times, I just want to highlight the existing C pop-up window.If there's no existing windows open, then only I want to open a new windows.
I've worked on a similar requirement for Winforms applicaiton.How do I go about this for a WPF application please?
Thanks.
First you'd need to declare myChildWindow outside of the click event so that it is accessible from multiple events. So,
MyGridView myChildWindow;
goes outside the click event, probably as a private variable.
Then, in your click event see if it's null, and if it is, create it.
if (myChildWindow == null)
{
myChildWindow = new MyGridView();
myChildWindow.Show();
}
You could keep a reference to the window and get rid of this when the window is closed:
MyGridView myChildWindow;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (myChildWindow == null)
{
myChildWindow = new MyGridView();
myChildWindow.Closed += MyChildWindow_Closed;
myChildWindow.Show();
}
else
{
myChildWindow.Activate();
}
}
private void MyChildWindow_Closed(object sender, EventArgs e)
{
myChildWindow.Closed -= MyChildWindow_Closed;
myChildWindow = null;
}

WinForms Form won't close on pressing X or Close() in C#

I'm having a bit weird problem with WinForm which seems to refuse to close for some weird reason. I've got very simple gui which sometimes doesn't react for me pressing X or when i use events on buttons it even reaches Close() and does nothing..
private void buttonZapisz_Click(object sender, EventArgs e) {
string plik = textBoxDokumentDoZaladowania.Text;
if (File.Exists(plik)) {
string extension = Path.GetExtension(plik);
string nazwaPliku = Path.GetFileName(plik);
SqlMethods.databaseFilePut(plik, comboBoxTypDokumentu.Text, textBoxKomentarz.Text, sKlienciID, sPortfelID, extension, nazwaPliku);
Close();
}
}
There are no events assigned to FormClosed or FormClosing. So how can I find out what's wrong. Sometimes X will work after the GUI is loaded but after i press Button to save some stuff to database it reaches Close() in that button event and it still is visible and does nothing. Can't use X, nor ALT+F4. I can go around GUI and choose other values for ComboBox without problem.
I call GUI like this:
private void contextMenuDokumentyDodaj_Click(object sender, EventArgs e) {
var lv = (ListView) contextMenuDokumenty.SourceControl;
string varPortfelID = Locale.ustalDaneListViewKolumny(listViewNumeryUmow, 0);
string varKlienciID = Locale.ustalDaneListViewKolumny(listViewKlienci, 0);
if (lv == listViewDokumentyPerKlient) {
if (varKlienciID != "") {
var dokumenty = new DocumentsGui(varKlienciID);
dokumenty.Show();
dokumenty.FormClosed += varDocumentsGuiKlienci_FormClosed;
}
} else if (lv == listViewDokumentyPerPortfel) {
if (varPortfelID != "" && varKlienciID != "") {
var dokumenty = new DocumentsGui(varKlienciID, varPortfelID);
dokumenty.Show();
dokumenty.FormClosed += varDocumentsGuiPortfele_FormClosed;
}
}
}
While I can't close GUI i can work on the main gui without problem too. I can open up same GUI and after opening new GUI i can quickly close it. GUI is very simple with few ComboBoxes,TextBoxes and one EditButton from Devexpress.
Edit: varDocumentsGuiPortfele_FormClosed code allows me to refresh GUI (reload ListView's depending on where the user is on now).
private void varDocumentsGuiPortfele_FormClosed(object sender, FormClosedEventArgs e) {
TabControl varTabControl = tabControlKlientPortfele;
if (varTabControl.TabPages.IndexOf(tabPageDokumentyPerKlient) == varTabControl.SelectedIndex) {
loadTabControlKlientPortfeleBezZmianyUmowy();
}
}
Paste this code into your form classes:
protected override void OnFormClosing(FormClosingEventArgs e) {
e.Cancel = false;
base.OnFormClosing(e);
}
When that works, you want to find out why you have Validating event handlers that don't want the form to be closed.
Next thing you want to verify is Debug + Exceptions, tick the Thrown box for CLR Exceptions. This makes sure you don't swallow an exception that prevents a form from closing. Or worse, the operating system swallowing the exception, a nasty Windows 7 problem.
If you are getting an Exception in your close method, then the Base closing method is never called.
Put a try{}catch{} around everything

How can I disable a tab inside a TabControl?

Is there a way to disable a tab in a TabControl?
Cast your TabPage to a Control, then set the Enabled property to false.
((Control)this.tabPage).Enabled = false;
Therefore, the tabpage's header will still be enabled but its contents will be disabled.
The TabPage class hides the Enabled property. That was intentional as there is an awkward UI design problem with it. The basic issue is that disabling the page does not also disable the tab. And if try to work around that by disabling the tab with the Selecting event then it does not work when the TabControl has only one page.
If these usability problems do not concern you then keep in mind that the property still works, it is merely hidden from IntelliSense. If the FUD is uncomfortable then you can simply do this:
public static void EnableTab(TabPage page, bool enable) {
foreach (Control ctl in page.Controls) ctl.Enabled = enable;
}
You can simply use:
tabPage.Enabled = false;
This property is not shown, but it works without any problems.
You can program the Selecting event on TabControler to make it impossible to change to a non-editable tab:
private void tabControler_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPageIndex < 0) return;
e.Cancel = !e.TabPage.Enabled;
}
You could register the "Selecting" event and cancel the navigation to the tab page:
private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPage == tabPage2)
e.Cancel = true;
}
Another idea is to put all the controls on the tabpage in a Panel control and disable the panel! Smiley
You could also remove the tabpage from the tabControl1.TabPages collection. That would hide the tabpage.
Credits go to littleguru # Channel 9.
Presumably, you want to see the tab in the tab control, but you want it to be "disabled" (i.e., greyed, and unselectable). There is no built-in support for this, but you can override the drawing mechanism to give the desired effect.
An example of how to do this is provided here.
The magic is in this snippet from the presented source, and in the DisableTab_DrawItem method:
this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new DrawItemEventHandler( DisableTab_DrawItem );
Extending upon Cédric Guillemette answer, after you disable the Control:
((Control)this.tabPage).Enabled = false;
...you may then handle the TabControl's Selecting event as:
private void tabControl_Selecting(object sender, TabControlCancelEventArgs e)
{
e.Cancel = !((Control)e.TabPage).Enabled;
}
This will remove the tab page, but you'll need to re-add it when you need it:
tabControl1.Controls.Remove(tabPage2);
If you are going to need it later, you might want to store it in a temporary tabpage before the remove and then re-add it when needed.
The only way is to catch the Selecting event and prevent a tab from being activated.
The most tricky way is to make its parent equals null (make the tab alone without parent):
tabPage.Parent = null;
And when you want to return it back (will return it back at the end of pages collection) :
tabPage.Parent = tabControl;
And if you want to return it back in a specific location among the pages you can use :
tabControl.TabPages.Insert(indexLocationYouWant, tabPage);
I had to handle this a while back. I removed the Tab from the TabPages collection (I think that's it) and added it back in when the conditions changed. But that was only in Winforms where I could keep the tab around until I needed it again.
I've removed tab pages in the past to prevent the user from clicking them. This probably isn't the best solution though because they may need to see that the tab page exists.
Using events, and the properties of the tab control you can enable/disable what you want when you want. I used one bool that is available to all methods in the mdi child form class where the tabControl is being used.
Remember the selecting event fires every time any tab is clicked. For large numbers of tabs a "CASE" might be easier to use than a bunch of ifs.
public partial class Form2 : Form
{
bool formComplete = false;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
formComplete = true;
tabControl1.SelectTab(1);
}
private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (tabControl1.SelectedTab == tabControl1.TabPages[1])
{
tabControl1.Enabled = false;
if (formComplete)
{
MessageBox.Show("You will be taken to next tab");
tabControl1.SelectTab(1);
}
else
{
MessageBox.Show("Try completing form first");
tabControl1.SelectTab(0);
}
tabControl1.Enabled = true;
}
}
}
I've solved this problem like this:
I've got 3 tabs and I want to keep user at the first tab if he didnt log in,
so on the SelectingEvent of TabControl I wrote
if (condition) { TabControl.Deselect("2ndPage"); TabControl.Deselect("3dPage"); }
The user cannot click on tabs to navigate, but they can use the two buttons (Next and Back). The user cannot continue to the next if the //conditions are no met.
private int currentTab = 0;
private void frmOneTimeEntry_Load(object sender, EventArgs e)
{
tabMenu.Selecting += new TabControlCancelEventHandler(tabMenu_Selecting);
}
private void tabMenu_Selecting(object sender, TabControlCancelEventArgs e)
{
tabMenu.SelectTab(currentTab);
}
private void btnNextStep_Click(object sender, EventArgs e)
{
switch(tabMenu.SelectedIndex)
{
case 0:
//if conditions met GoTo
case 2:
//if conditions met GoTo
case n:
//if conditions met GoTo
{
CanLeaveTab:
currentTab++;
tabMenu.SelectTab(tabMenu.SelectedIndex + 1);
if (tabMenu.SelectedIndex == 3)
btnNextStep.Enabled = false;
if (btnBackStep.Enabled == false)
btnBackStep.Enabled = true;
CannotLeaveTab:
;
}
private void btnBackStep_Click(object sender, EventArgs e)
{
currentTab--;
tabMenu.SelectTab(tabMenu.SelectedIndex - 1);
if (tabMenu.SelectedIndex == 0)
btnBackStep.Enabled = false;
if (btnNextStep.Enabled == false)
btnNextStep.Enabled = true;
}
tabControl.TabPages.Remove(tabPage1);
This is an old question, but someone may benefit from my addition. I needed a TabControl that would show hidden tabs successively (after an action was performed on the current tab). So, I made a quick class to inherit from and called HideSuccessive() on Load:
public class RevealingTabControl : TabControl
{
private Action _showNextRequested = delegate { };
public void HideSuccessive()
{
var tabPages = this.TabPages.Cast<TabPage>().Skip(1);
var queue = new ConcurrentQueue<TabPage>(tabPages);
tabPages.ToList().ForEach(t => t.Parent = null);
_showNextRequested = () =>
{
if (queue.TryDequeue(out TabPage tabPage))
tabPage.Parent = this;
};
}
public void ShowNext() => _showNextRequested();
}
There is the XtraTabPage.PageEnabled property allowing you to disable certain pages.
Here the solution that i implement:
private void switchTapPage(TabPage tabPage)
{
foreach(TabPage page in tabControl1.TabPages)
{
tabControl1.TabPages.Remove(page);
}
tabControl1.TabPages.Add(tabPage);
}
Basically, i just call this method sending the tabPage that i currently need to show, the method will remove all the tabPages on the tabControl and after that it will just add the one that i sent it.
So the rest of the tabHeaders will not shown and they will be inaccessible, because they dont even exists in the tabControl.
I took the idea from the #stormenet answer.
You can do it through the tabpages: tabPage1.Hide(), tabPage2.Show() etc.
In the form load event if we write this.tabpage.PageEnabled = false, the tabpage will be disabled.
Assume that you have these controls:
TabControl with name tcExemple.
TabPages with names tpEx1 and tpEx2.
Try it:
Set DrawMode of your TabPage to OwnerDrawFixed;
After InitializeComponent(), make sure that tpEx2 is not enable by adding this code:
((Control)tcExemple.TabPages["tpEx2").Enabled = false;
Add to Selection tcExemple event the code below:
private void tcExemple_Selecting(object sender, TabControlCancelEventArgs e)
{
if (!((Control)e.TabPage).Enabled)
{
e.Cancel = true;
}
}
Attach to DrawItem event of tcExemple this code:
private void tcExemple_DrawItem(object sender, DrawItemEventArgs e)
{
TabPage page = tcExemple.TabPages[e.Index];
if (!((Control)page).Enabled)
{
using (SolidBrush brush = new SolidBrush(SystemColors.GrayText))
{
e.Graphics.DrawString(page.Text, page.Font, brush, e.Bounds);
}
}
else
{
using (SolidBrush brush = new SolidBrush(page.ForeColor))
{
e.Graphics.DrawString(page.Text, page.Font, brush, e.Bounds);
}
}
}
It will make the second tab non-clickable.
I could not find an appropriate answer to the question. There looks to be no solution to disable the specific tab. What I did is to pass the specific tab to a variable and in SelectedIndexChanged event put it back to SelectedIndex:
//variable for your specific tab
int _TAB = 0;
//here you specify your tab that you want to expose
_TAB = 1;
tabHolder.SelectedIndex = _TAB;
private void tabHolder_SelectedIndexChanged(object sender, EventArgs e)
{
if (_TAB != 0) tabHolder.SelectedIndex = _TAB;
}
So, you don't actually disable the tab, but when another tab is clicked it always returns you to the selected tab.
in C# 7.0, there is a new feature called Pattern Matching. You can disable all tabs via Type Pattern.
foreach (Control control in Controls)
{
// the is expression tests the variable and
// assigned it to a new appropriate variable type
if (control is TabControl tabs)
{
tabs.Enabled = false;
}
}
Use:
tabControl1.TabPages[1].Enabled = false;
By writing this code, the tab page won't be completely disabled (not being able to select), but its internal content will be disabled which I think satisfy your needs.
The solution is very simple.
Remove/comment this line
this.tabControl.Controls.Add(this.YourTabName);
in IntializeComponent() method in MainForm.cs
MyTabControl.SelectedTab.Enabled = false;

Winforms c# - Set focus to first child control of TabPage

Say I have a Textbox nested within a TabControl.
When the form loads, I would like to focus on that Textbox (by default the focus is set to the TabControl).
Simply calling textbox1.focus() in the Load event of the form does not appear to work.
I have been able to focus it by doing the following:
private void frmMainLoad(object sender, EventArgs e)
{
foreach (TabPage tab in this.tabControl1.TabPages)
{
this.tabControl1.SelectedTab = tab;
}
}
My question is:
Is there a more elegant way to do this?
The following is the solution:
private void frmMainLoad(object sender, EventArgs e)
{
ActiveControl = textBox1;
}
The better question would however be why... I'm not entirely sure what the answer to that one is.
Edit: I suspect it is something to do with the fact that both the form, and the TabControl are containers, but I'm not sure.
Try putting it in the Form_Shown() event. Because it's in a container, putting in the Form_Load or even the Form() constructor won't work.
Try to use textbox1.Select() instead of textbox1.Focus(). This helped me few times.
You just need to add the Control.Select() for your control to this code. I have used this to set focus on controls during validation when there are errors.
private void ShowControlTab(Control ControlToShow)
{
if (!TabSelected)
{
if (ControlToShow.Parent != null)
{
if (ControlToShow.Parent.GetType() == typeof(TabPage))
{
TabPage Tab = (TabPage)ControlToShow.Parent;
if (WOTabs.TabPages.Contains(Tab))
{
WOTabs.SelectedTab = Tab;
TabSelected = true;
return;
}
}
ShowControlTab(ControlToShow.Parent);
}
}
}
I had a user control within another user control. textbox1.Select() worked for me but textbox1.Focus() did not work.
You can also try setting Tabstop to false, textbox1.Focus(), TabStop true.
private void ChildForm1_Load(object sender, EventArgs e)
{
ActiveControl = txt_fname;
}
i use this code it works fine on win tab control or dotnetbar supertab contrl

Categories

Resources