I would like to create a file dialog form that works like the one in MS Word. Specifically, you can select an existing file, create a new one, or delete a file, all within the file dialogue window. OpenFileDialog is a read-only deal. You can't create a new file with that control. SaveFileDialog can't be used to select an existing file. Is there a control that will do all of the above?
To create your custom dialog you should follow these steps:
Create a new form, call it MyFolderDialog
In the new form add the controls you need. For example, in order to let the user browse the file system, you can add a treeView and populate it using the classes System.IO.FileInfo and System.IO.FolderInfo.
Create a property in your form that reflects the user choice, something like public string SelectedFolder
Add a "Confirm" button and a "Cancel" button to your form
In the cancel button click event handler add the code this.DialogResult = DialogResult.Cancel;
In the confirm button click event handler add the code this.DialogResult = DialogResult.Ok;
Call your custom dialog like that
private string PickAFolder()
{
string selectedFolder = string.Empty;
using(var f = new MyFolderDialog())
{
if(f.ShowDialog() == DialogResult.Ok)
{
selectedFolder = f.SelectedFolder;
}
}
return selectedFolder;
}
Note that when the form is shown using ShowDialog method, the form won't dispose when it will be closed, so you can still read his properties after you confirmed. So it a good practice dispose it manually when you don't need it anymore. An elegant way to do it is to use the using keyword.
I hope this helps.
Related
hello I'm grabbing a windows form application in c # and have a question about a context menu I have my main form within the main form I have a picturebox and I created an event as the next mouse click
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("DISPONIBLE");
cm.MenuItems.Add("RESERVAR");
cm.MenuItems.Add("OCUPADA");
pictureBox1.ContextMenu = cm;
}
}
all going well so far shows me my contextual menu when I right click but when I choose the option to "AVAILABLE" another windows form show me someone who can help me please thanks
I think this is not the way. if you did so you need to call show for the context menu, you can set that menu at the initialization of the form or the control, you create the context menu one time it will be shown automatically, you don't have to create it each time you click the control, Add the following code to the constructor of the form just to check if it works
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("DISPONIBLE");
cm.MenuItems.Add("RESERVAR");
cm.MenuItems.Add("OCUPADA");
pictureBox1.ContextMenu = cm;
I've inherited some code and wanted to run this modification by you all, my concern is memory management.
Let us say I have a "base" Form with a bunch of buttons that open "dialog" forms. What is the recommended pattern for opening the dialog forms? Currently we display the "dialog" form like so (in the "base" Form code, upon button click):
ChangePasswordForm frm = new ChangePasswordForm();
frm.ShowDialog();
Then close it like so (in the "dialog" form code):
private void bCancel_Click(object sender, EventArgs e)
{
this.Close();
//this.Dispose(); <-- this is what I am considering adding.
}
My rationale for adding Dispose is that I am worried if this form is displayed and closed many times that each time a new instance of the form is created and its resources are never really released -- is this correct? Also, if the form has the "close" X in the top right, should I put a Dispose() call in the FormClosed event as well?
Thanks in advance.
I would use a using statement:
using (var frm = new ChangePasswordForm()) {
frm.ShowDialog();
}
Combine this with a DialogResult:
private void bCancel_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
}
Setting the DialogResult, will close the Dialog, and the caller/owner has some feedback.
And you don't have to worry about Close or Dispose.
According to MSDN you need to dispose under two conditions:
The two conditions when a form is not disposed on Close is when (1) it is part of a multiple-document interface (MDI) application, and the form is not visible; and (2) you have displayed the form using ShowDialog. In these cases, you will need to call Dispose manually to mark all of the form's controls for garbage collection.
MSDN Form.Close
Declaring the form in a using statement would be the appropriate way to handle this.
using (ChangePasswordForm frm = new ChangePasswordForm())
{
frm.ShowDialog();
}
I'm trying to write a text editor in WPF and I have a problem trying to locate the correct instance of an editor within a TabControl in response to a File -> Open action.
Tab items are added programatically and contain a WindowsFormsHost instance which in turn allows each tab to display an editor provided by the ScintillaNet WinForms component.
When a tab is selected and a user selects File -> Open, I need to locate the correct WindowsFormsHost instance based on the tab selection so I can load the file into the correct Scintilla instance.
Previously, I'd done this in WinForms simply by doing:
tabControl.TabPages[tabControl.SelectedIndex].Controls.Find("Scintilla")
How does this work in WPF?
To follow up regarding the solution I've gone with for now: I've decided to subclass the TabItem class and hold an additional property that references the WinForms ScintillaNet control:
public class CustomTabItem : TabItem
{
public Scintilla EditorControl
{
get; set;
}
}
And when I add new tabs, I just make sure that EditorControl is set to the new instance of Scintilla that is created too:
var editor = ScintillaFactory.Create();
var tab = new CustomTabItem()
{
Header = "Untitled",
Content = new WindowsFormsHost() { Name = "WinformsHost", Child = editor },
EditorControl = editor
};
tabControl.Items.Add(tab);
tab.Focus();
Now when an event is raised, I can query the selected tab and as cast to CustomTabItem in order to access the reference to the respective editor:
var editor = (tabControl.Items[tabControl.SelectedIndex] as CustomTabItem).EditorControl
editor.Text = "text here";
Hope that helps someone else.
i am developing an application in wpf using MVVM design pattern. i have a listbox when an item is slected then a dialog is open having the same record in editable mode. this dialog is binded with the selected item of the list. i have apply the validation rule for textbox using IDataErrorInfo. when the user update a record on dialogbox then at every key press, the selected record in listbox is also changed. if the user press save button then i submit changes to database. but if user click cancel button then i do not submit changes to database but the list box is updated with the current updation in GUI. when i refresh the list then old value appears again. My requirement is to update the listbox only when the user hit the save button but not on every key press on dialog box. I first fill the generic list with the linq to sql classes then bind the listbox with it. Please let me know what i have to do.
Thanks in advance
The problem is that you are editing the same object on both forms. You should pass the SelectedItem to the dialog form, but then re-query the database for the item that was passed to the constructor. This does two things: allows you to cancel the changes when the object has been edited, and provides the user with the most current data from the database.
Think of it this way... If the listbox contained data that was even a few minutes old, your user would be modifying data that may have already changed by another user running your application.
Once the user saves (or deletes) the record in the dialog form, you must then refresh the listbox. Typically I use the following method:
DialogViewModel:
// Constructor
public DialogViewModel(MyObject myObject)
{
// Query the database for the required object
MyObject = (from t in _dc.MyObjects where t.ID == myObject.ID
select t).Take(1).Single();
}
// First define the Saved Event in the Dialog form's ViewModel:
public event EventHandler Saved;
public event EventHandler RequestClose;
// Raise the Saved handler when the user saves the record
// (This will go in the SaveCommand_Executed() method)
EventHandler saved = this.Saved;
if (saved != null)
saved(this, EventArgs.Empty);
ListBox ViewModel
Views.DialogView view = new Views.DialogView();
DialogViewModel vm = new DialogViewModel(SelectedItem); // Pass in the selected item
// Once the Saved event has fired, refresh the
// list of items (ICollectionView, ObservableCollection, etc.)
// that your ListBox is bound to
vm.Saved += (s, e) => RefreshCommand_Executed();
vm.RequestClose += (s, e) => view.Close();
view.DataContext = vm;
view.ShowDialog();
I'm kinda stuck with this one so I hoped someone could help me.
I am doing a Winforms application and I need to show a Modal Dialog (form.ShowDialog) that returns a value (prompts the User some values and wraps them in a Object).
I just can't see how to do this rather than give a reference into the object or depending on some form of public Property to read the data afterwards.
I'd just like to have ShowDialog return something different, but that doesn't work.
Is thare some "good" way to do this?
I'm sure the problem isn't new, but since almost nobody seems to do Winforms any more I can't find any guidance on the web.
Add a static method to your form, like this:
public class MyDialog : Form
{
// todo: think of a better method name :)
public static MyObject ShowAndReturnObject()
{
var dlg = new MyDialog();
if (new dlg.ShowDialog() == DialogResult.OK)
{
var obj = // construct an instance of MyObject from dlg
return obj;
}
else
{
return null;
}
}
}
Now you can call this from your program thusly:
var myObject = MyDialog.ShowAndReturnObject();
... and if they cancel the dialog, myObject will be null.
Now, having said all that, I do believe that adding a property to your form's class which you then read from after calling ShowDialog() is the better approach.
You can create a public property inside the Dialog that represents the returning value:
/* Caller Code */
var dlg = new MyDialog();
if(dlg.ShowDialog() == DialogResult.OK)
MessageBox.Show(dlg.MyResult);
/* Dialog Code */
public string MyResult { get { return textBox1.Text; } }
private void btnOk_Click(object sender, EventArgs e)
{
DialogResult = System.Windows.Forms.DialogResult.OK;
this.Close();
}
Or you could create a new ShowDialog method inside your form class that does basically what Matt Hamilton's does. Maybe even an extension method if it's something you do to lots of forms in your problem.
The public property in the dialog form makes sense. However, do not close the dialog in the Ok button click event handler. When you assign the DialogResult property the dialog form will be hidden. Then in the calling form you can determine if Ok or Cancel was clicked by examining the DialogResult. Then you can access the public property if the Ok button was clicked and then dispose the dialog form. This should be done using a try-catch-finally block in the calling form or through a using statement. You must dispose of the modal dialog in order to prevent a memory leak.