WPF subwindow getting closed if i click the button on it - c#

if (VendorSettingWondow == null)
{
VendorSettingWondow = new VendorSettingWindow();
VendorSettingWondow.Top = this.Top;
VendorSettingWondow.Left = this.Left + this.Width/2;
//VendorSettingWondow.Visibility = Visibility.Visible;
VendorSettingWondow.injdf.Text = filename; // setting file name
VendorSettingWondow.inJDFVendorInfo.ItemsSource = inJDFVendors;
// VendorSettingWondow.inJDFVendorInfo.ItemsSource = vendorList.Vendors;
VendorSettingWondow.DBVendorList.ItemsSource = DBvendorList.Vendors;
VendorSettingWondow.ShowDialog();
}
I am creating a subwindow if some condition is satisfied in the main window like above. There are two buttons in my sub window. When i click the button the sub window is getting closed. I am using ShowDialog() because I want to control to be transferred from main window to sub window when the subwindow is created

Check the IsCancel property of the Button. If it is set to true, set it to false to prevent the button from closing the dialog.

Related

How to use a WPF ContextMenu with NotifyIcon

I want to open a WPF ContextMenu when the user clicks the system tray icon. With Windows Forms this is straight-forward, just call notifyIcon.ContextMenu = contextMenu and you're set.
On WPF we can not set the ContextMenu that easily because WPF's ContextMenu class is not related to Forms ContextMenu. The alternative I have been pursuing is to handle NotifyIcon's Click event to open the WPF-style ContextMenu.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// This is intended to be a system tray application so we hide the window
this.Visibility = Visibility.Hidden;
// Winform context menu
// The context menu closes when the user clicks anywhere outside the menu
// The user can navigate the menu with the keyboard arrows and close with ESC
var notifyIcon1 = new System.Windows.Forms.NotifyIcon();
var contextMenu = new System.Windows.Forms.ContextMenu();
var menuItem = new System.Windows.Forms.MenuItem();
menuItem.Text = "WinForm Menu Item";
contextMenu.MenuItems.Add(menuItem);
notifyIcon1.ContextMenu = contextMenu;
notifyIcon1.Icon = Properties.Resources.ico;
notifyIcon1.Visible = true;
// WPF context menu
// The user cannot close the menu by clicking outside its bounds
// Does not detect any keyboard input
var notifyIcon2 = new System.Windows.Forms.NotifyIcon();
notifyIcon2.Icon = Properties.Resources.ico;
notifyIcon2.Visible = true;
notifyIcon2.Click += NotifyIcon2_Click;
}
private void NotifyIcon2_Click(object sender, EventArgs e)
{
var contextMenu = new ContextMenu();
var menuItem = new MenuItem();
menuItem.Header = "WPF Menu Item";
contextMenu.Items.Add(menuItem);
contextMenu.IsOpen = true;
}
}
The issue with this approach is that the WPF ContextMenu never gets any hint that the user has navigated away from the menu and should close (Eg, when the user clicks outside the bounds of the menu). None of the Focus or MouseCapture events are ever triggered and I am unable to close the menu other than by clicking on one of its items.
So the question here, to put slightly different, is: how do I properly emulate the NotifyIcon's ContextMenu closing behavior using WPF's ContextMenu?
I faced similar issue. You can try if you want
notifyIcon1.ContextMenuStrip = new Forms.ContextMenuStrip();
notifyIcon1.ContextMenuStrip.Items.Add("YourMenuItem",null, MenuItemEvent);
I hope this will solve the problem.

Can't see Loaded, Initialized, Visible window

Simplified version
ParentWindow.ShowDialog()
Click default/Bring Up Child Window button in ParentWindow
Click event handler for default/Bring Up Child Window button does ParentWindow.Hide()
ChildWindow.ShowDialog()
Click ChildWindow's cancel/Go Back button
ParentWindow.Visibility = Visibility.Visible
ParentWindow is nowhere to be found.
I checked, and ParentWindow returns true for IsInitialized, IsLoaded, and IsVisible. I also Alt-Tabbed my way through all my windows to look for it - it's not hiding under anything.
Why can't I see ParentWindow anywhere?
Full version
parseSettingsWindow.ShowDialog()
Click default/Bring Up Fix Selector button in parseSettingsWindow
Click event handler for default/Bring Up Fix Selector button does:
a. ParentWindow.Hide()
b. parseSettingsWindow.GoToNextWindow flag set to true (Next window is Fix Selector)
while loop does fixSelector.ShowDialog() because it's not yet loaded
Click ChildWindow's cancel/Go Back button
while loop is entered again, goes to `case "Parse Settings" section
parseSettingsWindow.Visibility = Visibility.Visible
parseSettingsWindow is nowhere to be found
I checked, and parseSettingsWindow returns true for IsInitialized, IsLoaded, and IsVisible in the Immediate Window when pausing execution on the break; line of the "Parse Settings" while loop section. I also Alt-Tabbed my way through all my windows to look for it - it's not hiding under anything.
Why can't I see parseSettingsWindow anywhere?
Main class
public static bool UserPromptedSettingsWereWrittenToModel(ref Model model, ref ActiveFixes activeFixes, ref ActiveReports activeReports)
{
var viewModel = new ViewModel();
var parseSettingsWindow = new ViewPlusViewModel.ParseSettings();
parseSettingsWindow.InitializeComponent();
var fixSelector = new ViewPlusViewModel.FixSelector(viewModel);
fixSelector.InitializeComponent();
var seeAllFixesReports = new ViewPlusViewModel.SeeAllFixesReports();
seeAllFixesReports.InitializeComponent();
parseSettingsWindow.ShowDialog();
var nextWindowToOpen = "Fix Selector";
while (parseSettingsWindow.GoToNextWindow == true && fixSelector.GoToNextWindow == false)
{
switch(nextWindowToOpen)
{
case "Fix Selector":
if (fixSelector.IsLoaded)
{
fixSelector.Visibility = Visibility.Visible;
}
else
{
fixSelector.ShowDialog();
}
nextWindowToOpen = "Parse Settings";
break;
case "Parse Settings":
parseSettingsWindow.GoToNextWindow = false;
parseSettingsWindow.Visibility = Visibility.Visible;
nextWindowToOpen = "Fix Selector";
break;
}
}
if (parseSettingsWindow.GoToNextWindow == false)
{
parseSettingsWindow.Close();
if (fixSelector.IsLoaded) fixSelector.Close();
if (seeAllFixesReports.IsLoaded) { seeAllFixesReports.Close(); }
return false;
}
parseSettingsWindow.Close();
fixSelector.Close();
if (seeAllFixesReports.IsLoaded) { seeAllFixesReports.Close(); }
return true;
}
ParseSettingsWindow.cs
private void GoToNextWindow_Click(object sender, RoutedEventArgs e)
{
this.GoToNextWindow = true;
this.Hide();
}
You can't bring a hidden .ShowDialog() window back again via Window.Visibility. You need to use .ShowDialog() on it again. In addition, any buttons given the IsCancel = True property will no longer have that functionality even when using ShowDialog() again, so presses on that button will need to be handled manually.

How to delete button border after clicking outside of Form C#?

I made a simple button, but when i click outside of win form my button getting a black border. By the way i set BorderSize to "0" and it works great while i clicking inside of my form.
this.button.FlatAppearance.BorderSize = 0;
That's how it looks like.
it seems a focus problem. Try to reset the focus when the cursor leave the control.
Add these lines of code to your forms load event.
btn.FlatStyle = FlatStyle.Flat;//You can also use the popup flat style
btn.FlatAppearance.BorderColor = btn.Parent.BackColor;
btn.FlatAppearance.BorderSize = 0;
One simple workaround is to set the FlatAppearance.BorderColor of the Button to its Parent.BackColor:
this.button1.FlatAppearance.BorderColor = this.button1.Parent.BackColor;
You could set this Property subscribing to the ParentChanged event (or overriding OnParentChanged, if it's a Custom Control) if the Control can be assigned to another parent at some point.
You can also perform the same operation in batch, using the HandleCreated event and have all the Buttons (with FlatStyle = FlatStyle.Flat) subscribe to the event in the Form's constructor:
public Form1()
{
InitializeComponent();
foreach (Button button in this.Controls.OfType<Button>().Where(btn => btn.FlatStyle == FlatStyle.Flat))
{
button.HandleCreated += (s, e) => {
button.FlatAppearance.BorderColor = button.Parent.BackColor;
};
}
}

Add tabs to TabControl from another form

This is freaking me out, and if this is possible I would gladly appreciate the help.
I am a C# developer but have to do this in VB.NET.
So C# answers accepted as well.
I have a tab control on a form. This control does not have any tabs in it yet.
When the form loads, it loads a "Start" page. It adds the tab "tbpStart" and loads a form onto the tab page "frmStart".
On this start page, I have many Radio Buttons. When I click on one radio button, it should load other tabs on the main form.
The problem is how can I add tabs to one form's tab control from another form?
CODE:
When Main Form loads:
Try
'Load the Start Tab
Dim start As New frmTabStart
AddTabPage("Start", start)
Catch ex As Exception
PMComponentLibrary.PMMessageBox.ShowErrorMessage("Error occurred while trying to load the from.", ex)
End Try
Function on Main Form:
Public Sub AddTabPage(tabPageName As String, myForm As System.Windows.Forms.Form)
Try
myForm.TopLevel = False
myForm.Dock = DockStyle.Fill
myForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None
Dim NewTab As New System.Windows.Forms.TabPage
NewTab.Name = "tab" + tabPageName
NewTab.Text = tabPageName
NewTab.Controls.Add(myForm)
tbcMain.TabPages.Add(NewTab)
myForm.Show()
Catch ex As Exception
Throw ex
End Try
End Sub
When I click on one Radio Button on "Start Form" it executes this on a click_event:
If sender Is rdbWIPPostings Then
entity = New frmTabEntity()
mainForm.AddTabPage("Step 1", entity)
Application.DoEvents()
dte = New frmTabDate()
mainForm.AddTabPage("Step 2", dte)
wipSelect = New frmTabWIPSelect()
mainForm.AddTabPage("Step 3", wipSelect)
finish = New frmTabFinish()
mainForm.AddTabPage("Finish", finish)
End If
But the tabs does not get added to the Main Form.
What am I doing wrong?
Modify the constructor for frmTabStart to receive an instance of mainForm like this:
public frmTabStart(MainForm mainForm)
{
// store that in a field
}
and then when you need to add the tab:
_mainForm.AddTabPage(...);

Can't Add Tab Page To TabControl Inside The Constructor Of My WinForms Application

I have a C# Form application that has a TabControl in the main form. This TabControl is used to display multilple TabPages that contain a CustomControl. This CustomControl is just a Panel with a few buttons and a PictureBox.
Here is a picture of my app when it starts up. As you can see the tab control (the white area) is empty:
If the user clicks the "Add Image" button they are presented with an OpenFileDialog to select the image then the addImage method is called with the selected file:
private void doAddImage()
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = Constants.Global.IMAGE_FILE_FILTER();
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string imageFileName = openFileDialog.FileName;
addImage(imageFileName);
}
}
private void addImage(string imageFileName)
{
// Create a new bitmap and image preview custom control. Then create a new tab
// page and add the custom control to the tab page.
Bitmap bitMap = new Bitmap(imageFileName);
ImagePreviewCustomControl previewControl = new ImagePreviewCustomControl(bitMap);
previewControl.Dock = DockStyle.Fill;
TabPage tabPage = new TabPage(Path.GetFileNameWithoutExtension(imageFileName));
tabPage.Controls.Add(previewControl);
// Insert the new tab page to the right of the currently selected tab page
int selectedTabIndex = imagesTabControl.SelectedIndex;
imagesTabControl.TabPages.Insert(selectedTabIndex + 1, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex + 1;
}
As you can see, in the addImage method I create the Bitmap, CustomControl, and TabPage and then insert it into the TabControl.
I start my application, click the "Add Image" button, everything works just fine.
Here is a picture with a tab page added:
While I am testing my app I don't want to have to add an image manually using the OpenFileDialog every time so in my constructor I just call addImage with some fixed image file name that I want to test with:
public ImageViewerApp()
{
InitializeComponent();
addImage(#"C:\MyImages\Calculator-3-icon.png");
}
The problem I am having is that when I try to add the image in my constructor it doesn't show up in the TabControl. The application starts up blank (like the first picture).
As stated above when the application is already running and I click the "Add Image" button it gets added just fine.
I found a property in the TabControl class called Created which states:
"Gets a value indicating whether the control has been created"
So to try and figure out what's going on I write the value of Created to the console just before I call addImage in the constructor. (I have a custom console for debugging my Form applications.)
public ImageViewerApp()
{
InitializeComponent();
TestConsole.WriteLine(imagesTabControl.Created);
addImage(#"D:\Development\Work\Other\Stardock\Start8\_downloaded\Calculator-3-icon.png");
}
The value of Created just before the call to addImage in the constructor is:
False
I put another console output inside the addImage method:
private void doAddImage()
{
TestConsole.WriteLine(imagesTabControl.Created);
OpenFileDialog openFileDialog = new OpenFileDialog();
...
...
}
The value of Created after the app has started and the user presses the "Add Image" button is:
True
Why is it that the TabControl is not Created inside my constructor (even after the InitializeComponent() call) and the once the application is running it is Created?
=UPDATE========================================================================
Based on the suggestion by Hans Passant I have added the following code to my addImage method:
int selectedTabIndex = -1;
if (imagesTabControl.TabCount > 0)
{
selectedTabIndex = imagesTabControl.SelectedIndex;
}
else
{
selectedTabIndex = imagesTabControl.SelectedIndex + 1;
}
imagesTabControl.TabPages.Insert(selectedTabIndex, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex;
This doesn't work.
===============================================================================
=UPDATE2=======================================================================
int selectedTabIndex = imagesTabControl.SelectedIndex;
if (imagesTabControl.TabCount == 0) selectedTabIndex = -1;
imagesTabControl.TabPages.Insert(selectedTabIndex, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex;
This causes the following Exception:
{"InvalidArgument=Value of '-1' is not valid for 'index'.\r\nParameter name: index"}
===============================================================================
=UPDATE3=======================================================================
I tried the folllowing code:
int selectedTabIndex = imagesTabControl.SelectedIndex;
if (imagesTabControl.TabCount == 0) selectedTabIndex = -1;
imagesTabControl.TabPages.Insert(selectedTabIndex + 1, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex + 1;
This one doesn't throw an exception but again no tab page added after calling
addImage in the constructor.
===============================================================================
=UPDATE4=======================================================================
I have kindof given up on adding an image in the constructor. So instead I am using an enum RunMode and a variable RUN_MODE of that type. Then, if RUN_MODE == RunMode.TESTI call a method to add a random image when I click the button. (The OpenFileDialog is not used. I just parse through all the image files in the fixed directory IMAGE_DIRECTORY.
enum RunMode { NORMAL, TEST }
private static string IMAGE_DIRECTORY = #"D:\\Work\Images";
...
...
private void doAddImage()
{
if (RUN_MODE == RunMode.TEST)
{
addRandomImage();
return;
}
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = Constants.Global.IMAGE_FILE_FILTER();
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string imageFileName = openFileDialog.FileName;
addImage(imageFileName);
}
}
private void addRandomImage()
{
string[] allFiles = Directory.GetFiles(IMAGE_DIRECTORY);
List<string> imageFileNames = new List<string>();
foreach (string file in allFiles)
{
bool isImageFile = Constants.Global.IMAGE_EXTENSIONS.Contains(Path.GetExtension(file));
if (isImageFile)
{
imageFileNames.Add(file);
}
}
int randomIndex = new Random().Next(imageFileNames.Count);
addImage(imageFileNames.ElementAt(randomIndex));
}
This works. Now when I click the "Add Image" button during TEST_MODE I skip the
OpenFileDialog and just add a random image.
I would like to understand the issues with TabControl but at this point I just
need to continue development. My current solution works great.
As I person who like to understand everything I would like to use other people's
suggestions so I will keep monitoring this question for a solution.
===============================================================================
JonP's answer gave me the idea to just wait for the window handle to be created before inserting the tab, so I tried some events occuring between Form construction and Tab Control display.
I found it to work with both the Load or Shown events:
Right-click on the Form (the root, not child controls) in the Designer view > Properties > Events (flash icon) > Behavior > enter a method name for the Load or Shown event and confirm. To generate a Load event callback you can also double-click on the Form itself. This should generate something like this:
this.Load += new System.EventHandler(this.Form1_Load);
// or
this.Shown += new System.EventHandler(this.Form1_Shown);
Setup the tabs in the callback:
private void Form1_Load(object sender, EventArgs e)
{
// Add image (this will call imagesTabControl.TabPages.Insert(selectedTabIndex + 1, tabPage))
// This must be done on Load event because Insert requires
// the window handle, which is not ready in the constructor
addImage(#"path_to_image.png");
}
I have had this problem too and have found a workaround; I think it must be a bug with Insert():
Don't use Insert(), it usually does nothing, use Add() instead; this reliably adds a TabPage to the end of the collection.
After adding it swap it with the tab position where you actually want it.
imagesTabControl.TabPages.Add(tabPage);
// Now swap the two tabs:
imagesTabControl.TabPages[imagesTabControl.TabCount - 1] = imagesTabControl.TabPages[selectedTabIndex + 1];
imagesTabControl.TabPage[selectedTabIndex + 1] = tabPage;
Your mileage may vary of course :-)
Stop Press! An even better fix is to read the class's Handle member before calling Insert():
var handle = imagesTabControl.Handle;
Insert() works perfectly after you do that. Obvious isn't it???? The help page for Handle has this possible relevant Remark showing that the object actually does something when you read Handle:
The value of the Handle property is a Windows HWND. If the handle has not yet been created, referencing this property will force the handle to be created.
You could remove the TabControl from the designer and then instead just manually create the TabControl programmatically and add it to the Form immediately after InitializeComponent(). Then after you create the TabControl, call addImage(). Something like:
InitializeComponent();
TabControl tc = new TabControl();
tc.Location = new Point(10, 10);
tc.Size = new Size(100, 100);
tc.Visible = true;
tc.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Top);
this.Controls.Add(tc)
addImage("c:\pathToImage\image.bmp");

Categories