C# - How to transfer string from custom messagebox to form - c#

I have created a custom message box with a textbox for input which appears under a certain condition in form1. I want form1 to hold the value of the textbox if the submit btn is clicked. I am not getting the desired result.
This is similar to this however I don't want the processing to happen in the message box because the process requires so many variables that I would have to transfer to the messsagebox.
Form condition
}
else //NOT ALL APPROVE
{
string BtnClicked = DenyEmpRequest.ShowBox(AllDenied, EmpRequestID);
if (BtnClicked == "1") //SUBMIT BTN WAS CLICKED
{
DenyEmpRequest emp = new DenyEmpRequest();
string reason = emp.Reason_Txt.Text;
}
I know that it is because I am creating a new instance of the form that I used in the messagebox when I said "DenyEmpRequest emp = new DenyEmpRequest();". I don't know any other way to access the textbox in the messagebox.
Messagebox code
public static string ShowBox(string DenyEmp, string RequestID)
{
newMessageBox = new DenyEmpRequest();
newMessageBox.EmpToDeny_lbl.Text = DenyEmp;
EmpRequestID = RequestID;
newMessageBox.ShowDialog();
return Button_id;
}
private void SubmitBtn_Click(object sender, EventArgs e)
{
if (Reason_Txt.Text == string.Empty)
{
NoReason_Lbl.Visible = true;
}
else
{
Button_id = "1";
newMessageBox.Dispose();
}

Looks like you're overcomplicating it. If you are just trying to retrieve a string from a custom MessageBox, just make a form with an OK/Cancel button and a text box. Make a public string property that wraps around the value of the text box's "Text" property. And make the form set it's DialogResult to DialogResult.OK if the OK button is clicked, DialogResult.Cancel if the cancel button is clicked.
Then you can call this form with code shown below:
using (CustomMessageBox myMessageBox = new CustomMessageBox())
{
myMessageBox.Text = "Initial text"; // optionally set the initial value of the text box
if (myMessageBox.ShowDialog(this) == DialogResult.OK)
{
someVariable = myMessageBox.Text;
}
}
This is the format you should be using.
EDIT:
In reference to your comment, if you have a form with a text box on it, just write the property like this:
public class CustomMessageBox : Form
{
public string Text
{
get
{
return textBox.Text;
}
set
{
textBox.Text = value;
}
}
}

Related

How to check a box in CheckedListBox while the items in the list are custom objects in a C# window form application?

I am creating an "export to excel" windows form in c#.
The class contains a CheckedListBox and a "check all" button.
When clicking on the button I want to check all the items in the list in case that at least one checkbox is not checked or uncheck all the checkboxes in case they are all already checked.
I added a small complication, the list of the items is a list of custom objects (see private class inside): "ObjectToExport" class.
public partial class ExcelCustomExportForm : Form
{
private class ObjectToExport
{
private readonly IExcelExportable _form;
public ObjectToExport(IExcelExportable form)
{
_form = form;
}
public override string ToString()
{
return $"{_form.FormName} ({_form.CreatedDate.ToShortDateString()} {_form.CreatedDate.ToShortTimeString()})";
}
}
// each form in the list contains a gridview which will be exported to excel
public ExcelCustomExportForm(List<IExcelExportable> forms)
{
InitializeComponent();
Init(forms);
}
private void Init(List<IExcelExportable> forms)
{
foreach (IExcelExportable form in forms)
{
// Checked List Box creation
FormsCheckedListBox.Items.Add(new ObjectToExport(form));
}
}
private void CheckAllButton_Click(object sender, EventArgs e)
{
// checking if all the items in the list are checked
var isAllChecked = FormsCheckedListBox.Items.OfType<CheckBox>().All(c => c.Checked);
CheckItems(!isAllChecked);
}
private void CheckItems(bool checkAll)
{
if (checkAll)
{
CheckAllButton.Text = "Uncheck All";
}
else
{
CheckAllButton.Text = "Check All";
}
FormsCheckedListBox.CheckedItems.OfType<CheckBox>().ToList().ForEach(c => c.Checked = checkAll);
}
}
The problem is that the following line returns true even if not check box is checked:
var isAllChecked = FormsCheckedListBox.Items.OfType<CheckBox>().All(c => c.Checked);
Similar issue with the following line, if checkAll is true, no check box is checked:
FormsCheckedListBox.CheckedItems.OfType<CheckBox>().ToList().ForEach(c => c.Checked = checkAll);
What is the correct way to fix those two lines of code?
Your Problem begins here.
FormsCheckedListBox.Items.Add(new ObjectToExport(form));
and
var isAllChecked = FormsCheckedListBox.Items.OfType<CheckBox>().All(c => c.Checked);
You are adding instances of 'ObjectToExport' to the FormsCheckedListBox, but while filtering, you are checking filtering with CheckBox.
This means, your filtered query always return empty, and query never reaches All. This can be demonstrated with following example.
var list = new [] { 1,2,3,4};
var result = list.OfType<string>().All(x=> {Console.WriteLine("Inside All"); return false;});
The result of above would be True, and it would never print the "Inside All" text. This is what is happening with your queries.
You can find if any of the checkbox is checked using
var ifAnyChecked = checkedListBox1.CheckedItems.Count !=0;
To change state, you could do the following.
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
if (checkedListBox1.GetItemCheckState(i) == CheckState.Checked)
{
// Do something
}
}

c# getting the specific form to change specific value

How do I get specific opened form and change the value of specific property of the the form. I'm trying to cast Form to a specific form to change the values of that specific form.
I have multiple forms opened with dynamic name depending on the id
public UserChatFrm varUserChatFrm;
public void UserChatFrmOpener(string sendToEmpID)// function that will open multiple chat form depending n the senderid
{
if (Application.OpenForms["UserChatFrm" + sendToEmpID] == null)
{
varUserChatFrm = new UserChatFrm(sendToEmpID);
varUserChatFrm.Name = "UserChatFrm" + sendToEmpID;
varUserChatFrm.Tag = "UserChatFrm" + sendToEmpID;
varUserChatFrm.lblName.Text = sendToEmpID;
//varUserChatFrm.Text = sendToEmpID;
varUserChatFrm.MdiParent = Application.OpenForms["MainFrm"];
varUserChatFrm.Show();
}
varUserChatFrm.BringToFront();
}
Here are the opened forms
UserChatFrm UserChatFrm11 -> textbox1
UserChatFrm UserChatFrm12 -> textbox1 // I want to change the text of this
UserChatFrm UserChatFrm13 -> textbox1
UserlistFrm UserlistFrm ->listview
Here's my code to get that specific form
FormCollection fc = Application.OpenForms;
foreach (Form frm in fc)
{
if (frm.Name == "UserChatFrm" + rdr["emp_sys_id"].ToString())// this is queried in the database to naming specific form sample "UserChatFrm11"
{
UserChatFrm varUsrchat = frm; // not working error which has missing cast?
varUsrchat.textbox1.text = "sample"; // I want to change the value of specific
// or something like this
Application.OpenForms["UserChatFrm" + "12"].chatbox1.text = "sample"; //not working
}
}
Could you point out what am I missing?
I don't like the way you try to update the form, you can find a different solutions for this approach, my ideal way is create Interface and implement it for each form that you want update it, then cast the form to interface and Update the form:
public interface IFormUpdator<TModel> where TModel : class
{
void UpdateForm(TModel model)
}
Then implement this interface for each class:
public Form UserChatFrm : IFormUpdator<string>
{
public void UpdateForm(string model)
{
this.textbox1.text = model;
}
.....
}
then do the same for all other form which you want to update them
And you can update the form like this:
Application.OpenForms.OfType<IFormUpdator<string>>()
.ForEach(frm => frm.Update("Sample"));

how to get a dialogue result on custom dialoge box

So what I normally do to show a dialogue box and get a result in C# is,
MessageBoxResult result = MessageBox.Show("Wrong username or password", "Invalid details", MessageBoxButton.OK, MessageBoxImage.Hand);
string clear = "";
if (result == MessageBoxResult.OK)
{
username.Text = clear;
password.Password = clear;
}
However I've always hated this standard look it gives so I decided to make my own dialogue box in wpf. Problem is I'm not too sure exactly how to return a dialogue result with that. It's just a simple box with an okay button that's supposed to clear the username and password fields.
Is there any way to do this?
I found this on another question here on SO (here Where is Button.DialogResult in WPF?)
public class ButtonHelper
{
// Boilerplate code to register attached property "bool? DialogResult"
public static bool? GetDialogResult(DependencyObject obj)
{
return (bool?)obj.GetValue(DialogResultProperty);
}
public static void SetDialogResult(DependencyObject obj, bool? value)
{
obj.SetValue(DialogResultProperty, value);
}
public static readonly DependencyProperty DialogResultProperty =
DependencyProperty.RegisterAttached(
"DialogResult", typeof(bool?), typeof(ButtonHelper), new UIPropertyMetadata
{
PropertyChangedCallback = (obj, e) =>
{
// Implementation of DialogResult functionality
var button = obj as Button;
if (button == null)
throw new InvalidOperationException("Can only use ButtonHelper.DialogResult on a Button control");
button.Click += (sender, e2) =>
{
Window.GetWindow(button).DialogResult = GetDialogResult(button);
};
}
});
}
Then in the xaml for the "Ok" button
yourNameSpaceForTheButtonHelperClass:ButtonHelper.DialogResult="True"
Using the MVVM pattern, you could do this by exposing a DialogResult on the ViewModel your control is using. I highly recommend making an interface for this, thusly you can retrieve a result by casting to the interface regardless of the actual view model's type.
var control = new MyControl();
control.ShowDialog(); // Assuming your control is a Window
// - Otherwise, you'll have to wrap it in a window and event-bind to close it
result = (control.DataContext as IResultDialogVM).Result;
Alternatively, if you prefer to explicitly set your view models
var vm = new MyViewModel(question);
new MyControl { DataContext = vm }.ShowDialog();
result = vm.Result;

Custom dialog box control in c#

I have a question I hope some of you might be able to answer, I haven't found any ways to do this on google or here.
What I want:
- A custom control that functions just like an input box. (But it has to be a winform control that can be added to a form. Not a form.)
- It has to be able to grab the value from its text box and send it to the parent in the function it was called in.
Here is how I want to call it:
string str = MyBox.GetString("control title");
Can anyone help?
I don't know if this is event possible in c#. I couldn't figure it out, but if anyone can please answer!
You want something like this
public partial class MyBox : Form
{
public MyBox()
{
InitializeComponent();
}
public string ResultText { get; set; }
public static string GetString(string title)
{
var box = new MyBox {Text = title};
if (box.ShowDialog() == DialogResult.OK)
{
return box.ResultText;
}
return string.Empty;
}
private void okButton_Click(object sender, EventArgs e)
{
this.ResultText = txtUserInput.Text;
this.DialogResult = DialogResult.OK;
}
}
where MyBox would be a Form with TextBox - txtUserInput and an okay button linked to the okButton_Click event.
And you can make calls from other forms like this:
string userInput = MyBox.GetString("Title for MyBox");
If you want the box to reside on a form, you can just use a regular TextBox to get the inupt. Maybe eclose it in a GroupBox to give a "title", add a description label.
Lastly, and most importantly, add an "Update" Button to the GroupBox. Inside this button's Click handler, you can retrieve the value of the textbox with string str = textbox.Text.

Multi-tab application (C#)

I'm creating a multi-tabbed .NET application that allows the user to dynamically add and remove tabs at runtime. When a new tab is added, a control is added to it (as a child), in which the contents can be edited (eg. a text box). The user can perform tasks on the currently visible text box using a toolbar/menu bar.
To better explain this, look at the picture below to see an example of what I want to accomplish. It's just a mock-up, so it doesn't actually work that way, but it shows what I want to get done. Essentially, like a multi-tabbed Notepad.
View the image here: http://picasion.com/pic15/324b466729e42a74b9632c1473355d3b.gif
Is this possible in .NET? I'm pretty sure it is, I'm just looking for a way that it can be implemented.
You could use a simple extension method:
public static void PasteIntoCurrentTab(this TabControl tabControl)
{
if (tabControl.SelectedTab == null)
{
// Could throw here.
return;
}
if (tabControl.SelectedTab.Controls.Count == 0)
{
// Could throw here.
return;
}
RichTextBox textBox = tabControl.SelectedTab.Controls[0] as RichTextBox;
if (textBox == null)
{
// Could throw here.
return;
}
textBox.Paste();
}
Usage:
myTabControl.PasteIntoCurrentTab();
I suggest you keep some "current state" variables updated so you always have a pointer to the selected Tab Page, and its child control (in the case of a tabbed-notepad emulation discussed here : a TextBox). My preference would be to keep track of the TabPage<>TextBox connections using a Dictionary to avoid having to cast the TextBoxes if they are accessed using the TabPage.Controls route : the following code assumes you have a TabControl named 'tabControl1 on a Form :
Dictionary<TabPage, TextBox> dct_TabPageToTextBox;
int tabCnt = 1;
TabPage currentTabPage;
TextBox currentTextBox;
So, as you create each new TabPage at run-time you call something like this :
private void AddNewTabPage()
{
if (dct_TabPageToTextBox == null) dct_TabPageToTextBox = new Dictionary<TabPage, TextBox>();
currentTabPage = new TabPage("Page " + tabCnt.ToString());
tabControl1.TabPages.Add(currentTabPage);
currentTextBox = new TextBox();
dct_TabPageToTextBox.Add(currentTabPage, currentTextBox);
currentTabPage.Controls.Add(currentTextBox);
currentTextBox.Dock = DockStyle.Fill;
currentTextBox.Text = "sample text for page " + tabCnt.ToString();
tabControl1.SelectedTab = currentTabPage;
tabCnt++;
}
As the end-user changes the selected TabPage you can simply update your current state variables like this :
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
currentTabPage = tabControl1.SelectedTab;
currentTextBox = dct_TabPageToTextBox[currentTabPage];
MessageBox.Show("text in current Tab Page is : " + currentTextBox.Text);
}
So now have the code that is invoked by your menu choices applied only to the currentTextBox.
best, Bill
I tried this for fun ... I made a form with a ToolStripContainer, and a ToolStrip inside it, with the standard buttons (which includes the paste button). I renamed the paste button to pasteButton, and hooking everything up you get:
public Form2()
{
InitializeComponent();
TabControl tc = new TabControl();
toolStripContainer1.ContentPanel.Controls.Add(tc);
tc.Dock = DockStyle.Fill;
TextBox selectedTextBox = null;
pasteButton.Click += (_, __) => selectedTextBox.Paste(Clipboard.GetText(TextDataFormat.Text));
int pages = 0;
newTabButton.Click += (_,__) => {
TextBox tb = new TextBox { Multiline = true, Dock = DockStyle.Fill, ScrollBars = ScrollBars.Vertical };
TabPage tp = new TabPage("Page " + (++pages).ToString());
tc.Selected += (o, e) => selectedTextBox = e.TabPage == tp ? tb: selectedTextBox;
tp.Controls.Add(tb);
tc.TabPages.Add(tp);
tc.SelectedTab = tp;
selectedTextBox = tb;
};
}

Categories