Hello my application uses some OpenFileDialogs for file picking. Furthermore, I need a folder picker for which I used the CommonOpenFileDialog with the option IsFolderPicker = true.
Now when I open an OpenFileDialog in the app the parent window is locked and can't be used anymore, exactly the behavior I want.
But when I use the CommonOpenFileDialog I can still access the parent window and open even more CommonOpenFileDialogs.
The OpenFileDialog is intialized like this:
//init dialog
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = Path.GetFullPath(SecondQPcrFilePath);
openFileDialog.CheckFileExists = true;
openFileDialog.CheckPathExists = true;
openFileDialog.Multiselect = false;
openFileDialog.ReadOnlyChecked = false;
openFileDialog.ShowReadOnly = false;
//show dialog
bool? dialogResult = openFileDialog.ShowDialog();
The CommonOpenFileDialog like this:
//is this mvvm conform?
Button senderButton = (Button)sender;
string clickedButton = senderButton.Name;
//init dialog
CommonOpenFileDialog openPathDialog = new CommonOpenFileDialog();
openPathDialog.IsFolderPicker = true;
openPathDialog.EnsurePathExists= true;
openPathDialog.Multiselect = false;
openPathDialog.EnsureFileExists = false;
openPathDialog.AllowNonFileSystemItems = true;
if(clickedButton == "limsOpenButton")
{
openPathDialog.InitialDirectory = Path.GetFullPath(LimsPath);
}
else if(clickedButton == "qpcrOpenButton")
{
openPathDialog.InitialDirectory = Path.GetFullPath(QpcrPath);
}
//show dialog
CommonFileDialogResult dialogResult = openPathDialog.ShowDialog();
Is there a way to prevent that behavior? The common dialog does not have a property like Owner or similiar.
The common file dialog exposes an overload for the ShowDialog method.
public CommonFileDialogResult ShowDialog(Window window);
Pass the parent window to this method and the dialog will be modal.
var window = // Get the parent window here.
var dialogResult = openPathDialog.ShowDialog(window);
It looks like you use code-behind, so this would be the window. Alternatively you could use MainWindow or the Windows collection in Application.Current to find the window.
Related
Hello im having trouble with file dialog
Standard code, but it's freezing while selecting large files (600MB+ xls file that i need to first reformat to xlsb, then stream data from, but that is not important here).
What i wanted to achieve is to hide dialog when Open button is clicked, so that i could display Loading Message.
Yet im not sure how can i achieve that. Can i somehow subscribe to Open button?
OpenFileDialog openFile = new OpenFileDialog() { DereferenceLinks = false };
openFile.Title = "Select Supplier List";
openFile.Filter = "Excel files (*.*xls*)|*.*xls*";
try
{
if (openFile.ShowDialog() == true)
{
/* Takes long time to go after selection */
ViewModel.ReportPath = openFile.FileName;
ViewModel.FileTrueName = Path.GetFileName(ViewModel.ReportPath);
}
}
catch
{
ViewModel.ReportPath = null;
ViewModel.FileTrueName = null;
}
Wrapping code with task, helped :)
Some changes happened during searching for answer, based on comments.
Task.Run(() =>
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.Title = "Select Supplier List";
openFile.Filter = "Excel Files(*.xls; *.xlsx; *.xlsb; *.xlsm)| *.xls; *.xlsx; *.xlsb; *.xlsm";
try
{
if (openFile.ShowDialog() == true)
{
ViewModel.ReportPath = openFile.FileName;
ViewModel.FileTrueName = Path.GetFileName(ViewModel.ReportPath);
}
}
catch
{
ViewModel.ReportPath = null;
ViewModel.FileTrueName = null;
}
});
Due to some requirements, I have to close SaveFileDialog programmatically without using PINVOKE.
Is there any way to close SaveFileDialog other than using the PINVOKE way?
I had tried to close the owner form of the SaveFileDialog, but the SaveFileDialog still there.
What I had tried:
Close the form which execute the ShowDialog() of SaveFileDialog.
SaveFileDialog.Dispose()
Closing the owner window passed to the ShowDialog(owner); method should work. For example:
private static Form CreateDummyForm(Form owner) {
Form dummy = new Form();
IntPtr hwnd = dummy.Handle; // force handle creation
if (owner != null) {
dummy.Owner = owner;
dummy.Location = owner.Location;
owner.LocationChanged += delegate {
dummy.Location = owner.Location;
};
}
return dummy;
}
[STAThread]
static void Main() {
Form form = new Form();
form.Size = new Size(400,400);
Button btn = new Button { Text = "btn" };
btn.Click += delegate {
SaveFileDialog fsd = new SaveFileDialog();
int timeoutMillis = 5000;
Form dummy = CreateDummyForm(form); // Close disposes the dummy form
Task.Delay(TimeSpan.FromMilliseconds(timeoutMillis)).ContinueWith((t) => { dummy.Close(); dummy.Dispose(); }, TaskScheduler.FromCurrentSynchronizationContext());
fsd.ShowDialog(dummy);
fsd.Dispose();
};
form.Controls.Add(btn);
Application.Run(form);
}
If you use visual studio designer to add a SaveFileDialog, your Form will have a field with this dialog during the life time of your form.
It is way more efficient and way more easier create the SaveFileDialog only when needed. If you do this in a using statement, you won't have to take care of Disposing it, and certainly won't need PInvoke
private void MenuItem_FileSaveAs_Clicked(object sender, ...)
{
using (var dlg = new SaveFileDialog())
{
dlg.FileName = this.FileName;
dlg.InitialDirectory = ...
dlg.DefaultExt = ...
...
// Show the SaveFileDialog, and if Ok save the file
var dlgResult = dlg.ShowDialog(this);
if (dlgResult == DialogResult.OK)
{
// operator selected a file and pressed OK
this.FileName = dlg.FileName;
this.SaveFile(this.FileName);
}
}
}
try
{
Form frmShow = new Form();
TextBox txtShowAll = new TextBox();
frmShow.StartPosition = FormStartPosition.CenterScreen;
frmShow.Font = this.Font;
frmShow.Size = this.Size;
frmShow.Icon = this.Icon;
frmShow.Text = "All data";
txtShowAll.Dock = DockStyle.Fill;
txtShowAll.Multiline = true;
frmShow.Controls.Add(txtShowAll);
frmShow.ShowDialog();
StreamReader r = new StreamReader("empData.txt");
string strShowAllData = r.ReadToEnd();
txtShowAll.Text = strShowAllData;
r.Close();
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
I sure that is the file name is correct
when I run the program it shows an empty text box.
The result
I just noticed you are adding text to the textbox after showing the form in dialog mode. Why don't you move the frmShow.ShowDialog(); to the end of the try block just like I have done it in the code below, and make sure the empData.txt exists at its path.
try
{
Form frmShow = new Form();
TextBox txtShowAll = new TextBox();
frmShow.StartPosition = FormStartPosition.CenterScreen;
frmShow.Font = this.Font;
frmShow.Size = this.Size;
frmShow.Icon = this.Icon;
frmShow.Text = "All data";
txtShowAll.Dock = DockStyle.Fill;
txtShowAll.Multiline = true;
frmShow.Controls.Add(txtShowAll);
StreamReader r = new StreamReader("empData.txt");
string strShowAllData = r.ReadToEnd();
txtShowAll.Text = strShowAllData;
r.Close();
frmShow.ShowDialog();
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
As noted other places, the actual problem stems from the show dialog blocking before you can execute your dialog
There are a couple of things here
Why don't you create a dedicated Form i.e MyDeciatedShowAllForm, instead of dynamically creating it
If you are using something that implements IDisposable, Its best to use a using statement
Example
using(var r = new StreamReader("empData.txt"))
{
string strShowAllData = r.ReadToEnd();
txtShowAll.Text = strShowAllData;
}
Why don't you use File.ReadAllText instead, save your self some printable characters
Example
string strShowAllData = File.ReadAllText(path);
You probably need to set the TextBox to MultiLine
Example
// Set the Multiline property to true.
textBox1.Multiline = true;
// Add vertical scroll bars to the TextBox control.
textBox1.ScrollBars = ScrollBars.Vertical;
// Allow the RETURN key to be entered in the TextBox control.
textBox1.AcceptsReturn = true;
// Allow the TAB key to be entered in the TextBox control.
textBox1.AcceptsTab = true;
// Set WordWrap to true to allow text to wrap to the next line.
textBox1.WordWrap = true;
// Show all data
textBox1.Text = strShowAllData;
Why don't you check if the file exists first using File.Exists
Exmaple
if(!File.Exists("someFile.txt"))
{
MessageBox.Show(!"oh nos!!!!! the file doesn't exist");
return;
}
Lastly, and this is one you need to remember, you need to learn how to use the debugger and breakpoints, Navigating through Code with the Debugger. I mean, you should have known if there is text or not in your text file if you had just put a breakpoint on txtShowAll.Text = strShowAllData; there should be no doubt in your mind or ours.
I need to hide a window that is generated using Process class.
I made this procedure
_process = new Process()
{
EnableRaisingEvents = true
};
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.RedirectStandardOutput = true;
_process.StartInfo.CreateNoWindow = true;
_process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
_process.StartInfo.FileName = "app.exe";
_process.Start();
I need to hide a window that is generated for this process. Probably a child window of it.
I need a way to hide all child windows that a process call can generate.
When I click the button to open a file the OpenFileDialog box opens twice. The first box only opens the image files and the second box text files. If the user decides to close out the first box without choosing a file the second box pops up as well. I'm not sure what I am over looking on this issue. Any help would be appreciated. Thanks!
OpenFileDialog of = new OpenFileDialog();
of.Filter = "All Image Formats|*.jpg;*.png;*.bmp;*.gif;*.ico;*.txt|JPG Image|*.jpg|BMP image|*.bmp|PNG image|*.png|GIF Image|*.gif|Icon|*.ico|Text File|*.txt";
if (of.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
try
{
image1.Source = new BitmapImage(new Uri(of.FileName));
// enable the buttons to function (previous page, next page, rotate left/right, zoom in/out)
button1.IsEnabled = false;
button2.IsEnabled = false;
button3.IsEnabled = false;
button4.IsEnabled = false;
button5.IsEnabled = true;
button6.IsEnabled = true;
button7.IsEnabled = true;
button8.IsEnabled = true;
}
catch (ArgumentException)
{
// Show messagebox when argument exception arises, when user tries to open corrupted file
System.Windows.Forms.MessageBox.Show("Invalid File");
}
}
else if(of.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
try
{
using (StreamReader sr = new StreamReader(of.FileName))
{
textBox2.Text = sr.ReadToEnd();
button1.IsEnabled = true;
button2.IsEnabled = true;
button3.IsEnabled = true;
button4.IsEnabled = true;
button5.IsEnabled = true;
button6.IsEnabled = true;
button7.IsEnabled = true;
button8.IsEnabled = true;
}
}
catch (ArgumentException)
{
System.Windows.Forms.MessageBox.Show("Invalid File");
}
}
You're calling ShowDialog() twice:
if (of.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
//...
}
else if(of.ShowDialog() == System.Windows.Forms.DialogResult.OK)
Just call it once, and save the results:
var dialogResult = of.ShowDialog();
if (dialogResult == System.Windows.Forms.DialogResult.OK)
{
//...
}
// Note that the condition was the same!
else if(dialogResult != System.Windows.Forms.DialogResult.OK)
Edit:
If you want the second dialog to only show when the first is handled, you can do:
var dialogResult = of.ShowDialog();
if (dialogResult == System.Windows.Forms.DialogResult.OK)
{
//...
// Do second case here - Setup new options
dialogResult = of.ShowDialog(); //Handle text file here
}
You are calling ShowDialog both in the if and else if condition. That method is responsible for showing the dialog and only has the nice side effect of also telling you what the user clicked.
Store the method's result in a variable and check that in your if..elseif conditions instead.