I have a library. In the library, I have a button with a Green background color and Text as Go Green.
Now I made a winform project and dragged my Go green button in the form. On running the application, I noticed that the button color is changing to green but text is displayed as button1 (name of the class library).
My library looks like:
public class button : Button
{
public Seats()
{
button.BackColor = Color.Green;
button.Text = "Go Green";
}
}
I discovered that it is happening because InitializeComponent() method is called in the constructor of the form. And in designer.cs,
button.Text = "button1";
is called. How can I avoid that to happen. I want my text to be visible from my class library.
Note: When I manually removed the above code from the designer.cs, everything was working fine.
Easiest way - override button's Text property and make it hidden to designer serialization:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text
{
get { return base.Text; }
set { base.Text = value; }
}
Designer will add default button name, but when you build application, your text will be shown.
UPDATE: Another (harder) way - provide to designer default property value for your button. In this case you need reference System.Design.dll which is available only for full version of .net framework (not client profile version).
First: create control designer for your button
public class GoGreenButtonDesigner : System.Windows.Forms.Design.ControlDesigner
{
public override void OnSetComponentDefaults()
{
base.OnSetComponentDefaults();
Control.Text = "Go Green";
}
}
Last: add Designer attribute to your custom button class
[Designer(typeof(GoGreenButtonDesigner))]
public class GoGreenButton : Button
{
//...
}
That's it. Now when you drag button to form, it will have default text "Go Green" without any additional compilations.
Related
I created a custom Button, called AcceptButton, inheriting from System.Windows.Forms.Button
On the constructor I set a few properties, but most important, an image (A green checkmark), like this:
this.Image = Proyecto.Controls.Bases.Properties.Resources.ok_16;
When I add this control using VS2013 form designer, in another project that references the DLL I just created, the image is displayed correctly. But if I go into my control, and change the image in code, for example, to:
this.Image = Proyecto.Controls.Bases.Properties.Resources.ok_32;
The image is not changed in the projects that use this control (even if the solution is cleaned and regenerated). I followed the code generated by VS2013 and I found that the designer adds this line:
this.botonAceptar1.Image = ((System.Drawing.Image)(resources.GetObject("botonAceptar1.Image")));
For some reason, this resource is "hardcoded" in a resource file generated by VS, but it's not updated when I regenerate the solution.
Removing this line makes it work as expected (I can change the image in the "upstream" class and it'll be updated when the solution is regenerated).
Why is this happening?
How can I avoid this?
This happens due to the DesignerSerializationVisibility (MSDN) attribute. Try adding this property and these methods (MSDN) to your class:
public class MyButton : System.Windows.Forms.Button
{
public bool ShouldSerializeImage()
{
return !object.ReferenceEquals(this.Image, _BaseImage);
}
public void ResetImage()
{
this.Image = _BaseImage;
}
[System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible)]
public new Image Image
{
get { return base.Image; }
set { base.Image = value; }
}
private Bitmap _BaseImage;
public MyButton()
{
_BaseImage = Proyecto.Controls.Bases.Properties.Resources.ok_16;
this.Image = _BaseImage;
}
}
This replaces the default Image property and prevents the serialization you encountered. Furthermore it allows the designer to check if the property has it's default value and if it needs to be serialized. The default value is stored in a private field in the button class. This should correctly serialize (or not serialize) the properties.
Remove all buttons you have, recompile, readd the buttons to make sure.
I haven't done this for a while so am not quite sure how to do what I need, but I am sure it is pretty simple.
Basically, I have a form with a navigation pane. I want to make it so when a user clicks a button on that pane, say 'Home' it changes the content on the form, but doesn't actually switch to another form, if you get me?
As in, I would like the navigation pane to stay as it is the entire time and I only want the content of the form to change. It is almost like the 'TabControl' tool in Visual Studio's 'Toolbox' although instead of the tabs being directly above the content, I want them to be buttons displayed in a side pane. See the image below for a better understanding. Thanks!
(Side pane, and header stays the same regardless on what button is pressed, but the content changes.)
I'd implement this using UserControls. One UserControl is shown when a button is clicked. I'd create an interface (for example IView) that would be implemented by each UserControl that declares common functionality, like for example a method to check whether you can switch from one to another (like a form's OnClosing event) like this:
public interface IView
{
bool CanClose();
}
public UserControl View1: IView
{
public bool CanClose()
{
...
}
}
public UserControl View2: IView
{
public bool CanClose()
{
...
}
}
Then, switching views is quite easy:
private bool CanCurrentViewClose()
{
if (groupBox1.Controls.Count == 0)
return true;
IView v = groupBox1.Controls[0] as IView;
return v.CanClose();
}
private void SwitchView(IView newView)
{
if (groupBox1.Controls.Count > 0)
{
UserControl oldView = groupBox1.Controls[0] as UserControl;
groupBox1.Controls.Remove(oldView);
oldView.Dispose();
}
groupBox1.Controls.Add(newView);
newView.Dock = Dock.Fill;
}
In a button you could do this:
private void btnHome_Click(object sender, EventArgs e)
{
if (CanCurrentViewClose())
{
ViewHome v = new ViewHome();
// Further initialization of v here
SwitchView(v);
}
else
{
MessageBox.Show("Current View can not close!");
}
}
I've successfully used this approach on many occasions.
Simplest way is to place multiple Panels as content holders, implement content manager which keeps references to Panels and with it show/hide desired panel.
Simple, but for smaller apps it will work
You can simply use a TabControl which has as many TabPages as you want. For the TabControl you can set the Alignment property to Left
i have made a form with textbox and a save button in visual studio C#, entering text in textbox and clicking save creates a dynamic button on the other form in a vertical flowlayout panel,but when i re-run my application with a new text in the textbox,or restart my application then the previous button is lost, so tell me some logic or code that how can i save that dynamic button permanently in flowlayout panel and when new text is saved it creates another button below that of previously created one and so on.
For saving something done at the run-time, you either have to use a file, or use the Application Settings. A good reference about application settings can be found here on MSDN.
You can create a setting of a type like ButtonsList (which you have to write a class for) to store the button created. I said ButtonsList considering that you want to save more properties of each button. If you don't need to save anything else but the caption, you can set that property to be a string array.
Also, a very important thing, is that after the Save button is clicked, you have to call
Properties.Settings.Default.Save();
to keep the saved data while your application is not on.
Steps:
In Visual Studio, click PROJECT menu item.
Click <project-name> Properties item.
In the opened window, go to Settings on the left-side pane.
Click Setting in the table in the middle of the window, and type in the name of the setting that you want to create (e.g dynamicButtons).
Click on string drop-down, and choose System.Colletions.Specialized.StringCollection.
Go to your program and in the Save click event type:
Properties.Settings.Default.dynamicButtons.Add("button1_caption");
Properties.Settings.Default.Save();
Below is the code for a simple collection of ButtonInfos called ButtonsCollection:
class ButtonInfo
{
public string Caption { get; set; }
public Point Location { get; set; }
public Size ButtonSize { get; set; }
public ButtonInfo(string caption, Point location, Size size )
{
this.Caption = caption;
this.Location = location;
this.ButtonSize = size;
}
}
class ButtonsCollection : System.Collections.CollectionBase
{
public void Add(ButtonInfo bi)
{
List.Add(bi);
}
public void Remove(int index)
{
if (index > Count - 1 || index < 0)
{
System.Windows.Forms.MessageBox.Show("Index not valid!");
}
else
{
List.RemoveAt(index);
}
}
public ButtonInfo Item(int index)
{
return (ButtonInfo)List[index];
}
}
Since the visual designer for Settings in Visual Studio does not allow you to use custom type settings, you will have to do some manual work. You will find more about creating these custom settings here, on MSDN.
Hope my effort is not useless :)
You're going to want to save the information you need to recreate the button (maybe a label, the position or order) to a configuration file of some form. When you start up the application, check if the file exists. If it does, read it back in and then recreate your buttons.
I am designing a comparison dialog (shows several widgets with their characteristics in a grid). There is a features section where all available features are listed with a check box for each one. If the part has that feature, the checkbox is checked. These checkboxes need to be read-only so I've isEnabled=false. However visually the checkboxes (and the label content) show as greyed out.
Here are some important points:
The checkbox is a visual indicator of whether a part has a feature. There is no requirement for interaction.
The requirement is for a checkbox; I'd have to convince the powers that be to use something different.
What I want is an easy way to style/controltemplate a checkbox (and it's content) so it looks enabled, but doesn't react to user input.
Microsoft provides some of their default styles on MSDN and you can find the default style for a checkbox here: http://msdn.microsoft.com/en-us/library/ms752319(v=vs.85).aspx. Copy this style into your project, remove the Trigger for IsEnabled and set the style for your checkboxes to this new style.
On a side note, I'd recommend copying the style into a separate ResourceDictionary for reusablitiy and to keep the style from cluttering up your xaml files.
Create a custom control by inheriting from CheckBox, and in its constructor create a Click handler for it. Within that Click handler, put the following code:
((CheckBox)sender).Checked = !((CheckBox)sender).Checked;
Here's a complete example.
For Windows Forms:
namespace System.Windows.Forms
{
public class UnChangingCheckBox : System.Windows.Forms.CheckBox
{
public UnChangingCheckBox()
{
this.Click += new EventHandler(UnChangingCheckBox_Click);
}
void UnChangingCheckBox_Click(object sender, EventArgs e)
{
((CheckBox)sender).Checked = !((CheckBox)sender).Checked;
}
}
}
For WPF:
namespace System.Windows.Controls
{
public class UnchangingCheckBox : System.Windows.Controls.CheckBox
{
public UnchangingCheckBox()
{
this.Click += new System.Windows.RoutedEventHandler(UnchangingCheckBox_Click);
}
void UnchangingCheckBox_Click(object sender, System.Windows.RoutedEventArgs e)
{
if (((CheckBox)sender).IsChecked.HasValue)
((CheckBox)sender).IsChecked = !((CheckBox)sender).IsChecked;
}
}
}
If you place the above code in a new class in your Windows Forms or WPF project, they'll appear as new tools in your toolbox. Then all you need to do is drag your new "UnchangingCheckBox" control onto your form where you were using a CheckBox. You don't need to do any coding on your form.
Using this approach your code will still be able to do everything you could do to a CheckBox (set its value, etc). It's only user interaction that's been disabled in a way that doesn't interfere with the visual style.
The solution suggested above works well for Windows Forms, but I see what you mean about WPF and the check mark appearing for a second.
Try this instead:
namespace System.Windows.Controls
{
public class UnchangingCheckbox : CheckBox
{
public UnchangingCheckbox()
{
this.IsReadOnly = true;
}
public bool IsReadOnly
{
get { return !this.IsHitTestVisible && !this.Focusable; }
set
{
this.IsHitTestVisible = !value;
this.Focusable = !value;
}
}
}
}
You acquire a property called "IsReadOnly", which by default is set to true, and has the behaviour you require without the annoying "checkmark appears for a second" behaviour.
I'm trying to extend TextBox to add a Label to the left of it and treat it as one Control so I don't have to keep track of both of their sizes, locations, etc.
I've created a TextBoxWithLabel class that extends Control and has TextBox and Label fields, but I'm not really sure what to do for onPaint() - do I have to tell it to manually draw both items? If so, how? I'm guessing the default inherited behaviour doesn't go so far as 'check if I contain any child Controls and if I do, draw them'...
Is this even the best way to do it? I previously had my class extend TextBox and just added the Label field, but of course that didn't get added to the Panel containing the TextBoxWithLabel and so wasn't drawn.
Any suggestions or pokes in the right direction appreciated.
Thanks,
Alex
The typical approach here is a UserControl in which you put both the label and the text box. It is painful though, you have to add a lot of the properties and events of the text box to the user control so it at least resembles a text box. Ugly boilerplate code.
Another way to do it is to make a custom text box that sneaks in a label control on the parent. That completely behaves like a TextBox without having to do any work. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form. Set the Description property to the text you want to see appear in the label.
using System;
using System.Drawing;
using System.Windows.Forms;
class MyTextBox : TextBox {
private Label label;
public MyTextBox() {
label = new Label();
label.AutoSize = true;
label.Font = this.Font;
label.Location = this.Location;
label.Resize += new EventHandler(label_Resize);
}
protected override void OnParentChanged(EventArgs e) {
// Keeps label on the same parent as the text box
base.OnParentChanged(e);
label.Parent = this.Parent; // NOTE: no dispose necessary
}
private void moveLabel() {
// Keep label right-aligned to the left of the text box
label.Location = new Point(this.Left - label.Width - 10, this.Top);
}
private void label_Resize(object sender, EventArgs e) {
moveLabel();
}
protected override void OnLocationChanged(EventArgs e) {
base.OnLocationChanged(e);
moveLabel();
}
public string Description {
get { return label.Text; }
set { label.Text = value; }
}
public override Font Font {
get { return base.Font; }
set { base.Font = label.Font = value; }
}
}
Did you consider using a UserControl? The benefit of a usercontrol is that you can easily put your label and textbox with correct relative positioning.
Custom Control - An extension to an existing control
User Control - A composition of multiple existing controls
Choose your candidate.