I am designing an application using RibbonReportDesigner, which will let the user to create his own report template. That app will be a part of bigger application.
When user will save template I need to obtain result of Command Property (it is set on the button in designer as "SaveFile"). Why do I need this? I want to check if user really saved that template- if yes then i have to save report name to database. One of the problems is that the event of button click is executed before the dialog opening and i don't know how to check result of saving template.
How can I achieve this? I don't see in designer any appropiate events, which could be usefull for my purposes.
Code, which I use to fire event of saving file:
private void commandBarItem32_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
var result = commandBarItem32.Command.Equals(DialogResult.OK);
if (result == true)
{
//create object- report name etc. and save it to database
}
}
The reason I need to save it is that in bigger application there will be combobox with a list of created templates.
You dont need to hook all UI events,
it is much easier to just replace the ReportStorage (list, save, load report layouts)
ReportStorageExtension.RegisterExtensionGlobal(new MyCustomStorage());
where MyCustomStorage implements all CRUD methods to manage the layouts.
For more details you can follow the documentation
Related
I am currently working on updating a C# project that makes use of WinForms. One of the minor changes I want to make is as follows.
The project has a Form that currently allows the user to click a Button, which then opens a Folder Browser window where they can select a folder for the project to retrieve information from. The selected directory is entered into a TextBox after being selected. However, clicking on the TextBox also opens up a Folder Browser window. You are also currently unable to manually enter text into the TextBox.
What I want to do is (hopefully) pretty simple: I want the user to be able to enter a directory manually into the TextBox and for the project to accept that text input, and for the TextBox to not open a Folder Browser form upon being clicked.
Some other things to keep in mind:
I am not familiar with all the ins and outs of WinForms, so I could very well be missing something simple that I could do.
I am also in the process of completely restructuring the project, so if this is not possible in WinForms, but is possible in, say, WPF, that would not be a major obstacle for me in this case.
Here is the code for the Button, or at least the pertinent part, as a reference. txtProjectDir is the TextBox in question. Not much else is done with the TextBox in the code except for this part.
private void btnBrowse_Click(object sender, EventArgs e)
{
if (chooseProjectFolderDialog.ShowDialog() == DialogResult.OK)
{
clbConvertProjects.Items.Clear();
clbProjects.Items.Clear();
txtProjectDir.Text = chooseProjectFolderDialog.SelectedPath;
cur_projDir = txtProjectDir.Text;
Update: I have made some changes based on the input of several users (thanks to all of you, by the way). This is what the pertinent part of the code looks like now:
private void btnBrowse_Click(object sender, EventArgs e)
{
if (chooseProjectFolderDialog.ShowDialog() == DialogResult.OK)
{
clbConvertProjects.Items.Clear();
clbProjects.Items.Clear();
cur_projDir = txtProjectDir.Text;
I also had to change the TextBox to not be read-only, as well as remove a reference to the above method from its Event properties. Now it is able to accept user input, and doesn't open a Folder Browser when clicked into.
The only problem is this: if I only enter text directly into the TextBox, instead of selecting a folder via the browser popup, the program doesn't seem to properly accept the input (i.e., no information is being collected from the directory). Obviously, I still need to make the program accept user input, as it currently doesn't.
Update 2: After more suggestions (again, thanks guys) and good old trial-and-error, I have re-inserted the line txtProjectDir.Text = chooseProjectFolderDialog.SelectedPath; as removing it from the method had undesired effects on the program's functionality. I am still having an issue with the program accepting the user's manual input into the TextBox, though.
Update 3: As per #blaze_125's recommendation, I am going to have to create a new event for the TextBox when the user Leaves it. Thank you all for the help, I appreciate it!
However, clicking on the TextBox also opens up a Folder Browser window.
The only event for the TextBox is Action -> Click, which is set to btnBrowse_Click
What I want to do is (hopefully) pretty simple: I want the user to be able to enter a directory manually into the TextBox and for the project to accept that text input, and for the TextBox to not open a Folder Browser form upon being clicked.
If you don't want that event(aka action->click) to happen, then you must remove the text btnBrowse_Click from that textbox and leave it blank. That will remove the event you currently have linked to your textbox click.
There will be an even linked to the text box txtProjectDir to check this select the text box and in the properties select the lightning bolt.
I would assume that the even is a click into the textbox however.
If this is the case you probably want to remove this.
Now in terms of how to accept what is in the text box as the value you just want to reference the text and that is in the textbox whitch would be txtProjectDir.Text
private void btnBrowse_Click(object sender, EventArgs e)
{
if (chooseProjectFolderDialog.ShowDialog() == DialogResult.OK)
{
clbConvertProjects.Items.Clear();
clbProjects.Items.Clear();
cur_projDir = txtProjectDir.Text;
I have two Forms ( Form_Graph(Main Form), Form_Setting) and one Setting file. When I click on the Setting button, Form_Setting is opened using ShowDialog().
Form_Setting Contains three buttons OK, Cancel, Apply and setting option. Now the problem is when I change Setting and update setting file and after Click on Apply button, I'm not able to apply this setting to Form_Graph.
(Apply_OnClick saves the new setting in setting files.)
I have tried to refresh Form_Graph using:
Form_Graph obj = new Form_Graph();
Application.OpenForms["Form_Graph"].Refresh();
And also I have debugged it. All Form_Graph code is executing on both the way but hasn't applied the settings.
I know the first way never works because I created one new Form, but what about the second one?
Can anyone have a solution for this?
You don't need to create a new instance of parent in child. The best way to do this normally is to subscribe to events from the child form i.e. Form_Setting. You will need to create an event in the child form as follows:
public event EventHandler SettingsApplied;
public void NotifySettingsApplied(EventArgs e)
{
if(SettingsApplied != null)
SettingsApplied(this, e);
}
public void Apply_OnClick(object sender, EventArgs e)
{
//trigger event here to notify main form
NotifySettingsApplied(e);
}
Then in your parent form, subscribe to this event in the constructor or any other suitable place:
public Form_Graph()
{
fs = new Form_Setting();
fs.SettingsApplied += new EventHandler(fs_SettingsApplied);
}
void fs_SettingsApplied(object sender, EventArgs e)
{
//update your main graph form here
}
All i need to write code on Apply_OnClick
// Get Form_Graph object
Form_Graph objGraph = (Form_Graph)Application.OpenForms["Form_Graph"];
// Create a method in Form_Graph class which apply all setting to components
objGraph.UpdateGraph();
// Now refresh Form_Graph
objGraph.Refresh();
Based on your description and comments, you'll need to reload your form for the colors and graphics. You can do it in one of the 3 ways:
Call InitializeComponent() after you return from your settings dialog. This might be dangerous because InitializeComponent() will do other startup stuff too.
Reload your main form too after returning from settings dialog. You may or may not be able to do that based on the state of your main form.
Collect all the code that updates colors and graphics from InitializeComponent() and move it into a separate function. Call it after InitializeComponent() as well as when returning from your settings dialog.
I think the 3rd one would be the cleanest approach.
Edit
Another and generally much more clean way of doing this is through the use of Application Settings. You just go to your form designer, select your control and choose Application Settings from Properties window. Choose the property that you want to bind to a setting and then choose the corresponding setting from the dropdown. If the setting doesn't already exist, you just click the New button and the designer creates one for you.
These settings automatically get loaded and saved for you. No more manual stuff.
Edit 2
For immediate propagation of settings into control properties, you may need to change the default update event when binding your to your setting. To do that, go to your designer file and look for property binding statements:
this.TextBox1.DataBindings.Add("Text", Project1.Properties.Settings.Default.UserName, ""))
and set them to update immediately upon property change:
this.TextBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", global::Project1.Properties.Settings.Default, "UserName", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
I have a web form where I register a new employee. There're 3 parts in the form: Personal info, Address info, Special Status. But there's only one button for the whole form. When I submit the form all the information is updated to the database. So three Update statements are executed against the database. The methods are UpdatePersonalInfo, UpdateAddressInfo and UpdateSpStatus. Is there a way to check if there's been a change in any field in the certain part and run update method only if it's true. So something like this:
if (There's been any change to the personal data of the employee)
{
UpdatePersonalInfo;
}
if (There's been any change to the address information of the employee)
{
UpdateAddressInfo;
}
Sure I know, I can save all the previous values in a session object in PageLoad and then compare them one by one before running the method. But I thought maybe there's a magic way of doing this more easily.
Not sure that this is a better solution than any of the alternatives you already mentioned, but you could create a default handler to attach to the TextChanged, SelectedIndexChanged, etc events of your controls to keep track of which ones have changed.
List ChangedControls = new List(Of, String);
private void ChangedValue(object sender, System.EventArgs e) {
WebControl cntrl = (WebControl) sender;
ChangedControls.Add(cntrl.ID);
}
Then on your button click scour the ChangedControls list for the relevant controls.
We are developing a .NET application that uses a few custom controls.
One specific control is a simple "text editor" like control, where some content gets loaded into, based on the user's selection.
In cases where the user modifies the text in this control, and then makes a different selection which would overwrite that content, we would like to have the usual popup saying "Do you want to save pending changes? YES/NO/CANCEL".
I am considering which level of the application should be the one responsible for this: the control itself or the code that uses it?
I have been looking into the existing CancelEventArgs class, and considering using it, however i am not sure if this is a good fit for this specific scenario.
Example code i was thinking of:
When setting the text of the custom control, raise the "BeforeChanged" event. This will be handled and will allow to cancel the operation.
public void SetText(string text)
{
CancelEventArgs args = new CancelEventArgs();
// Raise the BeforeTextChanged event.
BeforeTextChanged(args);
// If the user cancelled the operation - do not modify text.
// For example, user code will check if needs saving, show the popup, etc.
if (args.Cancel)
{
return;
}
}
I don't think you need to handle this with events - it will just complicate matters. This is linear problem and a dialog popup will halt the current thread and give you enough control to handle the user's decision. The event in this scenario is the 'UserSelectionChanged' event. No need for more.
It looks ok in both cases but to keep your logic consistent; In case, you have encapsulated the file loading/contexts loading inside the user control then keep the use events. otherwise, handle it on the target form/control.
I am currently looking at a better approach to remember/persist previous state of the controls on a .NET Windows Form.
For example, there are 5 drop down list menu controls on a windows form. And user previously selected some items in these drop down menu. What I'd like to do here is: when this WinForm is loaded again, user's previous selections shall be recovered and remain the same.
For now, I can kinda think of a solution: store each selected value/index in a text file or registry key or something. And then read them every time the From is loaded.
But the thing is this approach would become inefficient to deal with a large number of controls and maintain their states.
So can anyone give me some thoughts or suggestions? What'd be the best way to do achieve it?
EDIT:
I just had a read about this article on MSDN, and this concerns me because I am doing the add-in project at the moment:
You cannot use application settings in an unmanaged application that
hosts the .NET Framework. Settings will not work in such environments
as Visual Studio add-ins, C++ for Microsoft Office, control hosting in
Internet Explorer, or Microsoft Outlook add-ins and projects.
You might want to look at Settings files
Saving User Settings
private void UserSettingsDemo_Load(object sender, EventArgs e)
{
txtServer.Text = Settings.Default.ServerNameSetting;
txtDatabase.Text = Settings.Default.DBNameSetting;
txtPassword.Text = Settings.Default.PasswordSetting;
txtUserId.Text = Settings.Default.UserIdSetting;
}
private void UserSettingsDemo_FormClosing(object sender, FormClosingEventArgs e)
{
Settings.Default.DBNameSetting = txtDatabase.Text;
Settings.Default.UserIdSetting = txtUserId.Text;
Settings.Default.PasswordSetting = txtPassword.Text;
Settings.Default.ServerNameSetting = txtServer.Text;
Settings.Default.Save();
}
Are you talking about keeping the previous state of a control after restarting the application? In that case, you probably won't have no choice than writing all the changes down in an configuration file for example.
If you are trying to navigate between different winforms and want to persist the changes, you could implement an history of controls. A datastructur like a stack should do the trick, with the following methods:
AddToHistory(Control control)
RetrieveLastOpen()
As far as you know what exactly you want to save it is ok to use smth like
(foreach var child in MainForm.Children.OfType<ComboBox>)
{
// Save properties of child into Dictionary<string, ComboBoxProperties>
}
and for loading you will do smth like this
(foreach var child in MainForm.Children.OfType<ComboBox>)
{
// Load properties of child from dictionary[child.Name]
}