Is it possible to convert input control to label? - c#

I am making a form that contains a lot of User Controls, each User Control is part of the form (contains TextBox, ComboBox etc).
User will use the form to update their information.
At end of submission, I need to display the original data and the data that the user have entered.
I wonder if is possible that I can replace the input control (TextBox etc) to Label?
So I can just simply use the same user control, then convert each of the input control to label to display the data... (I just don't really want to use readonly or disable)
Note: I used different dataset to map each of the User Control data....
What I was thinking to do is like to get the input control from Page.Controls:
aInputControl = new Label();
or...
Page.Controls.Remove(aInputControl);
Then somehow add new Label in same position in the page...
But I have no idea how...can't think of anything except add another div to surround each of the control...
I just wonder if it this is possible...
Thanks in advance.
================
Edit: Seems like making new user control is not a good way for me....I will just try to somehow map each original data and new data into a new User control, and write them into page...but anyway, thanks for the idea guys.

You can make a custom user control that contains a TextBox and a Label, and displays one or the other depending on whether or not it has a value.

I would create a user control or a web control to encapsulate that functionality. Add a Property to change the display mode and some logic in the control to determine which control to show.
Here is a sample of code to give you an idea, I can expand on this if you would like.
public class ReadOnlyControl<T> : WebControl where T : Control, ITextControl {
protected T inputControl;
protected Label lblLabel;
public bool IsReadOnly { get; set; }
public string Text { get; set; }
protected override void Render(HtmlTextWriter writer) {
Control control = IsReadOnly ? lblLabel : (Control)inputControl;
((ITextControl)control).Text = Text;
control.RenderControl(writer);
}
}

You may want to rethink your design. I recommend you have another view/page that displays the data summary after submit. Additionally, you will have more control of the formatting this way. I don't want to sound condescending, but it just sounds like you are being a little lazy.

Related

how create a datagrid with panel dynamically?

I'm french, so sorry for my bad english... But I hope that you will help me ;)
I'm developing a soft in c# with lot of information store in DB, like information about people.
I want display these information with a beautiful UI, like that :
For that, I created :
a first panel in Visual
a class for create sub panel dynamically
I make a loop and for each person, I call a method "createPanel" with the information of each person, and these sub panels created are added to the parent panel. The ID of each person is store in the "tag" parameter of the sub panel.
All work fine, but I don't really know how to add event in each sub panel.
As you can see in the link above, the user can click on a bookmark, or a icon for show a menu (the round with 3 point = icon "menu").
My question is how to add event for each sub panel dynamically ? For example I want display a menu for each sub panel when I click on the icon "menu", get the id store in the "tag" of the sub panel, and show a new form for manage information.
Thx for your help, I can add my code if necessary :)
Make a own user control for the panels you want to display containing all the controls from the toolbox you need.
public partial class MyControl : UserControl
{
...
}
In "MyControl" you define events for all things that can happen and must be handled externally of the control. Same as e.g. "SelectedIndexChanged" for combobox.
Your control class would then look like this:
public partial class MyControl : UserControl
{
public event EventHandler<MyImportantEventA> OnImportantThingHappend;
//Event-Invoker
protected virtual void OnOnImportantThingHappend(MyImportantEventA e)
{
OnImportantThingHappend?.Invoke(this, e);
}
}
//Data of your event. Customize as you like/need.
public class MyImportantEventA : EventArgs
{
public string Message { get; set; }
}
When you add your control dynamically, bind to the event(s) of your control:
myUserControl.OnImportantThingHappend += DoSomethingWithEvent;
Things the control can handle it self, don't need to be exposed as events.
E.g.:
"Close" may be something that must be handled externally. You need to remove the control, rearange you controls etc.
"Show Details" probably is something that can be handled completely inside of your control. Your control shows a message box or a fancy tooltip.

Reuse Grouped User Control from Control Library in WinForms

Is it possible when reusing a UserControl from a self-made library within a WinForm to change the text of a label or a string name behind a text box?
I'm currently learning WinForms development and wanted to reuse as much code as possible.
An example:
Login1 UserControl
Username1 = login.usertextbox.text
Password1 = login.passtextbox.text
HostName1 = login.hostname.text
Login2 UserControl
Username2 = login.usertextbox.text
Password2 = login.passtextbox.text
HostName2 = login.hostname.text
Login.cs
Username, Password, Hostname (textbox) and next button
The function behind the Login User Control Library will be exactly the same, just the results from login1 and login2 should store their results in different strings etc in the form.
I see how to reuse individual controls but not if this is possible. The value of login1 will be stored under a set of strings on the winform, the next button will then hide login1 and show login2.
The login user control was designed to a specific format too, so in addition to reusing the exact same code in the background, the format should also be the same so I didn't want to use individual buttons and have to reposition the location of each control.
If this isn't possible, is there something closer to let me reuse the existing control many times?
You can create some public properties for your Login user control to expose some properties you need. For example:
Public string UserName
{
get
{
return UsernameTextBox.Text;
}
set
{
UsernameTextBox.Text = value;
}
}
This way you can use this properties in your form, for example:
this.Login1.UserName
Another option is making your child controls public and access them directly. But using the previous method is recommended.

Accessing controls from different forms

I have a main form with some buttons, textboxes, labels, etc.
On a second form I would like to copy the text from the main forms textbox onto the second form.
Have tried:
var form = new MainScreen();
TextBox tb= form.Controls["textboxMain"] as TextBox;
textboxSecond.Text = tb.Text;
But it just causes an exception. The main screen textbox is initialised and contains text.
When I hover over form I can see all the controls are there.
What am I doing wrong?
Looking at the original code, there are two potential reasons for the NullReferenceException you are getting. First, tb is not defined in the code you provide so I am not sure what that is.
Secondly, TextBox textbox = form.Controls["textboxMain"] as TextBox can return null if the control is not found or is not a TextBox. Controls, by default, are marked with the private accessor, which leads me to suspect that form.Controls[...] will return null for private members.
While marking the controls as internal will potentially fix this issue, it's really not the best way to tackle this situation and will only lead to poor coding habits in the future. private accessors on controls are perfectly fine.
A better way to share the data between the forms would be with public properties. For example, let's say you have a TextBox on your main screen called usernameTextBox and want to expose it publicly to other forms:
public string Username
{
get { return usernameTextBox.Text; }
set { usernameTextBox.Text = value; }
}
Then all you would have to do in your code is:
var form = new MainForm();
myTextBox.Text = form.Username; // Get the username TextBox value
form.Username = myTextBox.Text; // Set the username TextBox value
The great part about this solution is that you have better control of how data is stored via properties. Your get and set actions can contain logic, set multiple values, perform validation, and various other functionality.
If you are using WPF I would recommend looking up the MVVM pattern as it allows you to do similar with object states.
PhoenixReborn is correct. The problem is that you are creating a new MainScreen, which means that new controls are created, so unless the text in your controls are initialized in the form constructor, they are going to be empty. Usually, the way to handle this is to pass the first form instance to the second form, like this:
SecondForm second = new SecondForm(this);
and in the second form:
public SecondForm (MainForm form)
{
// do something with form, like save it to a property or access it's controls
}
That way, the second form will have access to the first form's controls. You might consider making the properties you need to use public (in the designer properties pane). That way you can just do form.textboxMain.Text.

Correct UserControl Usage?

I just started breaking up my GUI application into UserControls. I have a TabControl with a bunch of TagePages. Obviously my MainForm.cs file was filled up with tons of events and controls etc and it got very messy quick.
So a previous question gained me the insight of how to create a UserControl. I intend on creating a UserControl for each TabPage and I was wondering how I can interact with Components on the main form or other UserControls.
Here is an example of a TabPage that I have made using a UserControl, which needs to Enable or Disable a button depending which TabPage is currently selected. Is this proper usage or is there a better way?
public partial class TabDetails : UserControl
{
private RequestForm fRequestForm;
public TabDetails()
{
InitializeComponent();
}
public void CustomInitialization(RequestForm pRequestForm)
{
fRequestForm = pRequestForm;
pRequestForm.TabControl_Main.SelectedIndexChanged += SelectedTabIndexChanged;
}
private void SelectedTabIndexChanged(object pSender, EventArgs pEvents)
{
fRequestForm.Button_SubmitRequest.Enabled = fRequestForm.TabControl_Main.SelectedTab != fRequestForm.Tab_Details;
}
}
In the MainForm.cs constructor I call:
this.tab_Details1.CustomInitialization(this);
This doesn't look like a good use of a user control. The user control should not decide how things in the form should behave when something is changed in the user control. A user control should be unaware of its container and should operate in any container.
The user control should notify the form that something has changed without telling what's the internal implementation and the form should decide what to do.
Example:
A user control named "NameUserControl" consists of TitleComboBox, FirstNameTextBox and LastNameTextBox. The user control wants to notify when one of the values has changed.
Wrong Way:
Create events:
TitleComboBox - SelectedIndexChanged.
FirstNameTextBox, LastNameTextBox - TextChanged.
The problems here:
You expose the internal controls behavior. What will happen if you want to change the TitleComboBox to TextBox? You'll have to change the event name and implementation.
You expose the fact that you use exactly 3 different controls. What will happen if you want to use the same text box for first and last name? You'll have to delete one event and change the name of the other.
Good Way:
Create only a single event: NameChanged and expose 1 property of FullName or three different properties for the values.
Either way the form subscribe to the event and decide what to do next.
Another thing to think about: the more you add more functionality to your user control, you either make it less reusable or you make its code more complex. For example, if you add validation inside the user control, you'll find one day that you need it without validation, so you'll add a property "bool ValidateData" or it will be so complicated that you'll need to build another control. One way to solve that is to build very small user controls, but combine them in one or more bigger user controls that fit all your current needs.

How to access UserConrtorl's controls in this situation

I have an UpdatePanel.
and I have a PlaceHolder inside this UpdatePanel.
There is a number of UserControls. One of them will be loaded dynamically,
according to some selections.
Control mycontrol = this.Page.LoadControl("myusercontrol.ascx");
myplaceholder.Controls.Add(mycontrol);
after loading a specific UserControl, I wanted to get the text written in
a TextBox that is in the loaded UserControl from the Parent page.
TextBox mytextbox = (TextBox) Page.FindControl("myusercontrol")
.FindControl("mytextbox");
The problem was the text is always empty !
What am I missing ?
I appreciate your help.
You should load your UserControl overriding OnInit as mentioned before. And why were you looking entire page to find the UserControl? You can use PlaceHolder.Controls...
This how I got it work
protected override void OnInit(EventArgs e)
{
Control userControl = this.Page.LoadControl("WebUserControl.ascx");
testPlaceHolder.Controls.Add(userControl);
userControl.ID="id";
base.OnInit(e);
}
protected void testButton_Click(object sender, EventArgs e)
{
Control testUserControl = (Control)testPlaceHolder.Controls[0];
//Control testUserControl=(Control)testPlaceHolder.FindControl("id");
TextBox mytextbox = (TextBox)testUserControl.FindControl("testTextBox");
testButton.Text = mytextbox.Text;
}
When you say that the text is always empty, do mean the TextBox object is null or literally the .Text of the textbox is empty?
Remember that in web applications you have to post back to the server to refresh results and update controls among other things.
Try posting back to the server and seeing if that helps.
Have you considered adding a property to your user control to return the text?
eg:
public class YourControl : UserControl
{
public string Text
{
get
{
return this.TextBox1.Text;
}
}
}
Usually, User Controls are used for encapsulation - you wrap up all the details of controls, behaviour etc in a UC so other code doesn't have to deal with it.
By referring to controls within the UC directly - by name or ID - you're breaking the model. Can I suggest you don't do this, instead if you need to get information from the UC you add a property, event or method to it that the container can call.
That way if you need to change the UC - control names, types, styles, or additional logic is used later - you only need to change that property/event/method in the UC, not in the (for example) 100 places it might be used in the code.
If you could let us know why you need this information or more specific details about the example, perhaps we can suggest some code to implement this.
So, what should I do ?
Just get the posted values manually.
Request.Form[yourcondeol.UniqueID]
by debugging this you can see all the posted data.
Request.Form

Categories