Hiiho! I am developing a dashboard view using Xamarin.Forms.
Now I want to allow a user to drag and drop my icons to rearrange my Grid. But for some reason I get no visual representation of the drag event on UWP. The "DragStarted" event those fire tho. Here is my code
This is my custom renderer in UWP.
[assembly: ExportRenderer(typeof(DashboardIcon), typeof(DashboardIconRenderer))]
namespace Paraply.Droid.Custom_Renderers
{
class DashboardIconRenderer : ViewRenderer<DashboardIcon, Windows.UI.Xaml.FrameworkElement>
{
public DashboardIconRenderer()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<DashboardIcon> e)
{
base.OnElementChanged(e);
if (this == null)
return;
this.CanDrag = true;
this.DragStarting += OnDragStarting;
//this.Holding += HandleHoldEvent;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
this.CanDrag = true;
}
private void OnDragStarting(object sender, DragStartingEventArgs e)
{
//This fires
}
}
My contentpage in Xamarin.Forms, or its the funciton that fills my Grid
public void InflateServices(IList<InstalledServiceModel> services)
{
int count = 0;
serviceBoard.Children.Clear();
foreach (InstalledServiceModel service in services)
{
DashboardIcon icon = new DashboardIcon(service.Name, service.IconURL, service.Id);
var p = new TapGestureRecognizer();
p.CommandParameter = icon;
p.SetBinding(TapGestureRecognizer.CommandProperty, "IconClick");
icon.GestureRecognizers.Add(p);
icon.Holding += HandleHoldEvent;
serviceBoard.Children.Add(icon, count % 3, count / 3);
count++;
}
}
Now every DashboardIcon is a class that derives from Grid. It looks like this
public class DashboardIcon : Grid
{
//public event EventHandler<DashboardHoldingEventArgs> Holding;
//public void OnHolding(DashboardHoldingEventArgs e) { Holding(this, e); }
public DashboardIcon(string title, string url, int id = -1)
{
Title = title;
URL = url;
ServiceId = id;
/*
UI design
*/
HorizontalOptions = LayoutOptions.FillAndExpand;
VerticalOptions = LayoutOptions.FillAndExpand;
RowDefinitions.Add(new RowDefinition() { Height = new GridLength(0.6, GridUnitType.Star) });
RowDefinitions.Add(new RowDefinition() { Height = new GridLength(0.4, GridUnitType.Star) });
image = new Image()
{
Source = url,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Aspect = Aspect.AspectFit
};
text = new Label()
{
Text = title,
HorizontalTextAlignment = TextAlignment.Center,
TextColor = Color.Black
};
Children.Add(image, 0, 0);
Children.Add(text, 0, 1);
}
Now my OnDragStarting function does fire just fine. But for some reason I get no visual representation of the view I'm dragging, I was expecting the view to follow my finger until I drop it?
In OnDragStarting you can set e.DragUI.SetContentFromBitmap() for example. There you can specify what you want to see while dragging (the image probably). Also here you could set this.Opacity = 0.2; so it gets transparent or invisible.
Related
I'm having a weird behavior with a class I created inheriting from PictureBox.
It's a class made to behave like a button (basically what I care about is the mouse enter, mouse leave, mouse down, mouse up events).
Everything works perfectly until I add the TextLabel (code below) to the control of my customized class. It shows the label, centered and everything as I wanted, but the events I mentioned before (and every other event in that matter) becomes disabled, for some reason it won't fire them.
I would like to know what is the reason for that behavior and if there is any fix for it.
public class RoundedButton : PictureBox
{
private readonly Image r_BasicImage = RoundedButtonCheck2.Properties.Resources.basicRoundedButtonIcon as Image;
private readonly Image r_HoverImage = RoundedButtonCheck2.Properties.Resources.hoverRoundedButtonIcon as Image;
private readonly Image r_ClickImage = RoundedButtonCheck2.Properties.Resources.clickRoundedButtonIcon as Image;
private string m_Text;
private Font m_Font;
public Color m_TextColor;
private Label LabelText = new Label();
public RoundedButton()
{
this.Width = 130;
this.Height = 40;
this.Image = r_BasicImage;
this.BackColor = Color.Transparent;
this.SizeMode = PictureBoxSizeMode.StretchImage;
this.MouseDown += RoundedButton_MouseDown;
this.MouseUp += RoundedButton_MouseUp;
this.MouseEnter += RoundedButton_MouseEnter;
this.MouseLeave += RoundedButton_MouseLeave;
LabelText.Font = ButtonFont;
ButtonTextColor = Color.Black;
//PROBLEMATIC CODE HERE:
***********this.Controls.Add(LabelText);***************
}
public Color ButtonTextColor
{
get
{
return m_TextColor;
}
set
{
m_TextColor = value;
LabelText.ForeColor = m_TextColor;
}
}
public Font ButtonFont
{
get
{
if (m_Font == null)
{
m_Font = new Font("Calibri Light", 12);
}
return m_Font;
}
set
{
m_Font = value;
LabelText.Font = ButtonFont;
adjustLabel();
}
}
public string ButtonText
{
get
{
return m_Text;
}
set
{
m_Text = value;
LabelText.Text = m_Text;
adjustLabel();
}
}
private void adjustLabel()
{
const int MARGIN = 10;
LabelText.AutoSize = true;//needed for autosize calculation of the label;
Size newSize = new Size(LabelText.Size.Width, LabelText.Size.Height); ;
LabelText.AutoSize = false;//after auto-calculated size of the label, set to false in order for centering label works well.
this.MinimumSize = newSize;
this.Size = new Size(newSize.Width + MARGIN, newSize.Height + MARGIN);
LabelText.TextAlign = ContentAlignment.MiddleCenter;
LabelText.Dock = DockStyle.Fill;
}
private void RoundedButton_MouseLeave(object sender, EventArgs e)
{
RoundedButton hoveredButton = sender as RoundedButton;
if (hoveredButton != null)
{
hoveredButton.Image = r_BasicImage;
hoveredButton.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
private void RoundedButton_MouseEnter(object sender, EventArgs e)
{
RoundedButton hoveredButton = sender as RoundedButton;
if (hoveredButton != null)
{
hoveredButton.Image = r_HoverImage;
hoveredButton.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
private void RoundedButton_MouseUp(object sender, MouseEventArgs e)
{
RoundedButton clickedButton = sender as RoundedButton;
if (clickedButton != null)
{
clickedButton.Image = r_BasicImage;
clickedButton.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
private void RoundedButton_MouseDown(object sender, MouseEventArgs e)
{
RoundedButton clickedButton = sender as RoundedButton;
if (clickedButton != null)
{
clickedButton.Image = r_ClickImage;
clickedButton.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
}
Hello I made a custom text box with an associated label.
and I have a custom Form.
when on a form if I drag drop my custom textbox from the toolbox and set it's properties I can see that it works. However what I would like to do is when I'm on my custom control where I have a TableLayoutPanel (with 3 rows)
on row index 1(mid row) I would like to add my custom controls programatically.
when I do this the text label is somewhere else then the textbox.
My Code and the Image to my problem is below:
MyCustomTextBox:
public class MyLbTextBox : TextBox
{
#region CustomProperties
private Label AssociatedLabel = new Label();
private string _myLbText;
public string MyTextLabel
{
get => _myLbText;
set
{
_myLbText = value;
AssociatedLabel.Text = _myLbText ?? _myBindingField;
Size s = TextRenderer.MeasureText(AssociatedLabel.Text, AssociatedLabel.Font);
AssociatedLabel.Location =
new Point(Location.X - s.Width - AssociatedLabel.Padding.Right, Location.Y);
var MyMargin = this.Margin;
MyMargin.Left = 100;
this.Margin = MyMargin;
}
}
#endregion
private string _myBindingField;
public string MyBindingField
{
get { return _myBindingField; }
set
{
_myBindingField = value;
}
}
private MyJoins.MyExpressions _myExpression;
public MyJoins.MyExpressions MyExpression
{
get => _myExpression;
set => _myExpression = value;
}
public MyLbTextBox()
{
_myExpression = MyJoins.MyExpressions.Equals;
ParentChanged += MyLbTextBox_ParentChanged;
LocationChanged += MyLbTextBox_LocationChanged;
Disposed += MyLbTextBox_Disposed;
}
private void MyLbTextBox_Disposed(object sender, EventArgs e)
{
AssociatedLabel.Dispose();
}
private void MyLbTextBox_LocationChanged(object sender, EventArgs e)
{
Size s = TextRenderer.MeasureText(AssociatedLabel.Text, AssociatedLabel.Font);
AssociatedLabel.Location =
new Point(Location.X - s.Width - AssociatedLabel.Padding.Right, Location.Y);
}
private void MyLbTextBox_ParentChanged(object sender, EventArgs e)
{
AutoAddAssociatedLabel();
}
private void AutoAddAssociatedLabel()
{
if (Parent == null) return;
AssociatedLabel.Padding = new Padding(3);
Size s = TextRenderer.MeasureText(AssociatedLabel.Text, AssociatedLabel.Font);
AssociatedLabel.Location =
new Point(Location.X - s.Width - AssociatedLabel.Padding.Right, Location.Y);
Parent.Controls.Add(AssociatedLabel);
}
}
By the way, this is how I add my controls:
after adding my controls through the property grid
this is how I set them on the screen
private void _mySearchFields_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_mySearchFields == null) return;
foreach (var searchField in _mySearchFields)
{
if (MySearchFieldsPanel.Contains(searchField.MyControl)) continue;
MySearchFieldsPanel.Controls.Add(searchField.MyControl, 1, 0);
}
var myHeight = MySearchFieldsPanel.Controls.Cast<Control>().Sum(variable => variable.Height);
MyBdPanel.RowStyles[1].Height = myHeight + 40;
}
I appreciate any help
This line is a reason of all problems:
Parent.Controls.Add(AssociatedLabel);
This is bad idea if you are creating composite controls (composite = consisting from several real controls). That will cause layout problems you have experienced and more.
Instead consider either:
Utilize UserControl to create composition.
Create custom control (like you do) but without more controls. If you need label - draw it as text in OnPaint while allocating some space: fixed with margin, adjustable with some property or dynamic with measuring text.
Is there a way to have the color dialog display on the form without the window border? To make things a bit more clearer, I want it sort of like the one used in the Paint program so that I'm able to change colors of lines drawn on a picturebox without having to open up the dialog again and again:
I'm placing it inside a vertical groupbox, and I want it to be able to fit in it. Can it be done?
You can easily build it yourself. Use a TableLayoutPanel or FlowLayoutPanel and a add a list of small PictureBox with the background color set on the color you want. Then handle the Click event to return/use their background color.
private void Form1_Load(object sender, EventArgs e)
{
pictureBox3.Click += HandleColorPick;
pictureBox4.Click += HandleColorPick;
pictureBox5.Click += HandleColorPick;
pictureBox6.Click += HandleColorPick;
pictureBox7.Click += HandleColorPick;
pictureBox8.Click += HandleColorPick;
pictureBox9.Click += HandleColorPick;
}
private void HandleColorPick(object sender, EventArgs e)
{
var s =(PictureBox) sender;
MessageBox.Show(s.BackColor.ToString());
}
You'll have to create your own palette.
Here's a usercontrol i wrote with comments. I've added a OnSelectionChanged event that will be fired when user changes color.
You can either use the designer to specify colors, events and other properties or you can hard-code them.
public partial class UserControl1 : UserControl
{
// The event raised when a user changes color
[Category("Behavior")]
public event EventHandler OnSelectionChanged;
/*
* Properties
*
*/
private Color[] m_Colors = new Color[] {}; // Colors on the palette
private Color m_SelectedColor; // Stores selected color
private int m_MaxColorsPerLine = 14; // Max colors per line
public Color[] Colors
{
get { return m_Colors; }
set { m_Colors = value; }
}
[Browsable(false)]
public Color SelectedColor
{
get { return m_SelectedColor; }
}
public int MaxColorsPerLine
{
get { return m_MaxColorsPerLine; }
set { m_MaxColorsPerLine = value; }
}
public UserControl1()
{
InitializeComponent();
}
private void UserControl1_Load(object sender, EventArgs e)
{
this.Controls.Clear();
int COLOR_WIDTH = 16;
int COLOR_HEIGHT = 16;
// Border colors
Color NEUTRAL_COLOR = Color.Black;
Color HIGHLIGHTED_COLOR = Color.Orange;
Color SELECTED_COLOR = Color.Red;
// Populate the palette
for(int i = 0; i < m_Colors.Length; ++i)
{
// Get where the current color should be positioned.
int linePos = (int)Math.Floor((double) i / m_MaxColorsPerLine);
int colPos = i % m_MaxColorsPerLine;
int posX = COLOR_WIDTH * colPos;
int posY = COLOR_HEIGHT * linePos;
// Create the panel that will hold the color
Panel pnl = new Panel();
pnl.Width = COLOR_WIDTH;
pnl.Height = COLOR_HEIGHT;
pnl.Location = new Point(posX, posY);
pnl.BackColor = m_Colors[i];
pnl.ForeColor = NEUTRAL_COLOR;
// Change border color when highlighted
pnl.MouseEnter += (s, args) => pnl.ForeColor = HIGHLIGHTED_COLOR;
// Change border color when mouse leaves
pnl.MouseLeave += (s, args) =>
{
if (pnl.Tag != null && (bool)pnl.Tag == true)
{
pnl.ForeColor = SELECTED_COLOR; // restore selected border color on mouse leave if selected
}
else
{
pnl.ForeColor = NEUTRAL_COLOR; // restore normal border color on mouse leave if not selected
}
};
// Change border color when selected
pnl.Click += (s, args) =>
{
if (pnl.Tag == null || (bool)pnl.Tag == false)
{
pnl.ForeColor = SELECTED_COLOR;
pnl.Tag = true; // Use the Tag member to store whether the color is selected
m_SelectedColor = pnl.BackColor;
// Raise the SelectionChanged event if this panel is not already selected
if (OnSelectionChanged != null)
{
OnSelectionChanged(this, EventArgs.Empty);
}
}
// Unselect other colors
foreach (Panel otherColor in this.Controls)
{
if (otherColor == pnl)
continue;
if (pnl.Tag != null && (bool)pnl.Tag == true)
{
otherColor.ForeColor = NEUTRAL_COLOR;
otherColor.Tag = false;
}
}
};
// Draw borders
pnl.Paint += (s, args) =>
{
Rectangle outterRect = args.ClipRectangle;
Rectangle innerRect = new Rectangle(outterRect.X + 1, outterRect.Y + 1, outterRect.Width - 3, outterRect.Height - 3);
// Draw outter rectangle
args.Graphics.DrawRectangle(
new Pen(
new SolidBrush(pnl.ForeColor), 2),
outterRect);
// Draw inner rectangle
args.Graphics.DrawRectangle(
new Pen(
Brushes.White, 1),
innerRect);
};
// Finally, add color panel to the control
this.Controls.Add(pnl);
}
}
}
Why not some 3rd party opensource control?
http://www.codeproject.com/Tips/638824/Yet-Another-Color-Picker-for-Csharp-VB-NET-WinForm
or
http://www.blackbeltcoder.com/Articles/controls/colorpicker-controls-for-winforms
I am just creating an application in C# Windows Forms for Book Store application
The process i am doing here is
1.Inserting Book name, book image to Database.
2.Now i need to retrieve as in the image to forms but all should be dynamically created like if i have two books this panel with picture box, button and that textbook should be created and values should be showed there..
If i have got three entereids in DB means the three picture box, button and that textbook should be created and values should be showed there in the form.
is there any way to solve this out..
Need to Create these controls Dynamically according to the "n" number of rows in Database
For more Clarity about my question please see the image
Create a user control that contains the image, text box and button. Iterate over your list of records retrieved from the database and create new instance of the user control for each item. Add the user controls to the parent control's Controls collection.
You can achieve this using list view control:
you can get more details on this:
http://www.dotnetperls.com/listview
http://www.c-sharpcorner.com/UploadFile/9a3ae2/using-listview-control-windows-form-application3/
http://www.java2s.com/Code/CSharp/GUI-Windows-Form/ListViewExample.htm
I hope it will help you.,. :)
Use UserControl to build your custom control (image, text field, button) (http://msdn.microsoft.com/en-us/library/aa302342.aspx)
Use FlowLayoutPanel or TableLayoutPanel to add controls on your form.
Create Winforms project and add this file:
CtrlBuyBook.cs
using System;
using System.Drawing;
using System.Windows.Forms;
namespace UserControls
{
public class CtrlBuyBook : UserControl
{
public int BookID { get; set; }
public int Quantity
{
get { return (int)nudQuantity.Value; }
set { nudQuantity.Value = value; }
}
public Image Cover
{
set { picCover.Image = value; }
}
public CtrlBuyBook()
{
InitializeComponent();
}
private void btnBuy_Click(object sender, System.EventArgs e)
{
OnBuyBook(EventArgs.Empty);
}
public event EventHandler<EventArgs> BuyBook;
private void OnBuyBook(EventArgs e)
{
var handler = BuyBook;
if (handler != null)
{
handler(this, e);
}
}
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.picCover = new System.Windows.Forms.PictureBox();
this.btnBuy = new System.Windows.Forms.Button();
this.nudQuantity = new System.Windows.Forms.NumericUpDown();
((System.ComponentModel.ISupportInitialize)(this.picCover)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudQuantity)).BeginInit();
this.SuspendLayout();
this.picCover.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.picCover.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picCover.Location = new System.Drawing.Point(4, 4);
this.picCover.Name = "picCover";
this.picCover.Size = new System.Drawing.Size(143, 167);
this.picCover.TabIndex = 0;
this.picCover.TabStop = false;
this.btnBuy.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnBuy.Location = new System.Drawing.Point(95, 177);
this.btnBuy.Name = "btnBuy";
this.btnBuy.Size = new System.Drawing.Size(52, 20);
this.btnBuy.TabIndex = 2;
this.btnBuy.Text = "Buy";
this.btnBuy.UseVisualStyleBackColor = true;
this.btnBuy.Click += new System.EventHandler(this.btnBuy_Click);
this.nudQuantity.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.nudQuantity.Location = new System.Drawing.Point(4, 177);
this.nudQuantity.Name = "nudQuantity";
this.nudQuantity.Size = new System.Drawing.Size(85, 20);
this.nudQuantity.TabIndex = 3;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.nudQuantity);
this.Controls.Add(this.btnBuy);
this.Controls.Add(this.picCover);
this.Name = "ctrlBuyBook";
this.Size = new System.Drawing.Size(150, 200);
((System.ComponentModel.ISupportInitialize)(this.picCover)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudQuantity)).EndInit();
this.ResumeLayout(false);
}
private System.Windows.Forms.PictureBox picCover;
private System.Windows.Forms.Button btnBuy;
private System.Windows.Forms.NumericUpDown nudQuantity;
}
}
Next add FlowLayoutPanel and Button on your form.
In form code at the begining add this:
private int _bookCount = 0;
Then on button's click event add following code:
var control = new CtrlBuyBook();
control.BookID = ++_bookCount;
control.Cover = null;
control.Quantity = 1;
control.BuyBook += new EventHandler<EventArgs>(control_BuyBook);
flpPanel.Controls.Add(control);
And finally the method for user control's BuyBook event:
private void control_BuyBook(object sender, EventArgs e)
{
var control = (CtrlBuyBook)sender;
MessageBox.Show(string.Format("Customer wants to buy book with ID: {0}. Quantity: {1}", control.BookID, control.Quantity));
}
All you need is to retrieve your books from DB and display on form and handle BuyBook event from User Control.
That's all.
It's simple to achieve what you want. You just need to create some UserControl for each book or a Panel is OK. I'll introduce to using the Panel for it. Something like this:
public class BookPanel : Panel
{
public string BookName
{
get { return text.Text; }
set { text.Text = value; }
}
public Image BookCover
{
get { return pic.Image; }
set { pic.Image = value; }
}
public event EventHandler BuyBook;
public string BuyButtonText
{
get { return button.Text; }
set { button.Text = value; }
}
//inner child controls
PictureBox pic = new PictureBox();
TextBox text = new TextBox();
Button button = new Button();
public BookPanel()
{
pic.Parent = text.Parent = button.Parent = this;
pic.Top = 5;
text.Left = pic.Left = 5;
button.Text = "Buy";
button.Width = 50;
button.Anchor = AnchorStyles.Right | AnchorStyles.Bottom;
text.Anchor = AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right;
pic.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;
pic.SizeMode = PictureBoxSizeMode.StretchImage;
button.Click += (s, e) =>
{
EventHandler handler = BuyBook;
if (handler != null) handler(this, EventArgs.Empty);
};
}
bool init;
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
if (!init)
{
text.Width = Width - button.Width - 12;
button.Left = text.Right + 5;
pic.Height = Height - 35;
pic.Width = Width - 10;
text.Top = pic.Bottom + 5;
button.Top = text.Top - 2;
init = true;
}
}
}
//Usage
bookPanel1.BookCover = yourImage;
//Try this to see how the Buy button works
bookPanel1.BuyBook += (s, e) => {
MessageBox.Show(bookPanel1.BookName);
};
NOTE: The code above is not complete, you don't have full ability to customize the look and feel of your TextBox, Button and PictureBox, however you can add code to do so, the code is a little much. I think for a simple control, it's enough. You should also notice the use of Dock property, the Margin and Padding properties and other layout and container controls like Panel, FlowLayoutPanel, TableLayoutPanel to customize your own control.
To use it in a FlowLayoutPanel, try this code:
flowLayoutPanel1.AutoScroll = true;
for (int i = 0; i < 100; i++) {
new BookPanel {
Parent = flowLayoutPanel1,
Width = 150,
Height = 200,
BorderStyle = BorderStyle.FixedSingle,
BookCover = yourImageList[i]
}.BuyBook += buyBook;
}
private void buyBook(object sender, EventArgs e){
BookPanel book = sender as BookPanel;
//your code goes here ....
}
I was wondering how could I do this. I know I can use the button component but it has the little gray stuff around it when I give it a image. With image button how could I show another image for the hover effect
You want to create a button with no border but displays different images when the user hovers over it with the mouse? Here's how you can do it:
Add an ImageList control to your form at add two images, one for the button's normal appearance and one for when the mouse is hovering over.
Add your button and set the following properties:
FlatStyle = Flat
FlatAppearance.BorderColor (and maybe MouseOverBackColor & MouseDownBackColor) to your form's background color
ImageList = the ImageList you added to the form
ImageIndex to the index value of your normal image
Code the MouseHover and MouseLeave events for the button like this:
// ImageList index value for the hover image.
private void button1_MouseHover(object sender, EventArgs e) => button1.ImageIndex = 1;
// ImageList index value for the normal image.
private void button1_MouseLeave(object sender, EventArgs e) => button1.ImageIndex = 0;
I believe that will give you the visual effect you're looking for.
Small summary (Border, MouseDownBackColor, MouseOverBackColor)
FlatApperance
BorderColor = Black or what ever you want
BorderSize = can be set to 0
MouseDownBackColor = Transparent
MouseOverBackColor = Transparent
Text = none
For MouseDown:
// ImageList index value for the mouse down image.
private void button1_MouseDown(object sender, MouseEventArgs e) => button1.ImageIndex = 2;
You can assign the BackgroundImage property for the button. You can also use the OnMouseEnter and OnMouseExit events to change the background as per your request.
See BackgroundImage OnMouseEnter OnMouseLeave
I also needed an image button, but I wanted one like the ToolstripMenuButton.
With the correct borders and colors on hover.
So I made a custom control to do just that:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace LastenBoekInfrastructure.Controls.Controls
{
[DefaultEvent("Click")]
public class ImageButton : UserControl
{
public string ToolTipText
{
get { return _bButton.ToolTipText; }
set { _bButton.ToolTipText = value; }
}
public bool CheckOnClick
{
get { return _bButton.CheckOnClick; }
set { _bButton.CheckOnClick = value; }
}
public bool DoubleClickEnabled
{
get { return _bButton.DoubleClickEnabled; }
set { _bButton.DoubleClickEnabled = value; }
}
public System.Drawing.Image Image
{
get { return _bButton.Image; }
set { _bButton.Image = value; }
}
public new event EventHandler Click;
public new event EventHandler DoubleClick;
private ToolStrip _tsMain;
private ToolStripButton _bButton;
public ImageButton()
{
InitializeComponent();
}
private void InitializeComponent()
{
var resources = new ComponentResourceManager(typeof(ImageButton));
_tsMain = new ToolStrip();
_bButton = new ToolStripButton();
_tsMain.SuspendLayout();
SuspendLayout();
//
// tsMain
//
_tsMain.BackColor = System.Drawing.Color.Transparent;
_tsMain.CanOverflow = false;
_tsMain.Dock = DockStyle.Fill;
_tsMain.GripMargin = new Padding(0);
_tsMain.GripStyle = ToolStripGripStyle.Hidden;
_tsMain.Items.AddRange(new ToolStripItem[] {
_bButton});
_tsMain.Location = new System.Drawing.Point(0, 0);
_tsMain.Name = "_tsMain";
_tsMain.Size = new System.Drawing.Size(25, 25);
_tsMain.TabIndex = 0;
_tsMain.Renderer = new ImageButtonToolStripSystemRenderer();
//
// bButton
//
_bButton.DisplayStyle = ToolStripItemDisplayStyle.Image;
_bButton.Image = ((System.Drawing.Image)(resources.GetObject("_bButton.Image")));
_bButton.ImageTransparentColor = System.Drawing.Color.Magenta;
_bButton.Name = "_bButton";
_bButton.Size = new System.Drawing.Size(23, 22);
_bButton.Click += bButton_Click;
_bButton.DoubleClick += bButton_DoubleClick;
//
// ImageButton
//
Controls.Add(_tsMain);
Name = "ImageButton";
Size = new System.Drawing.Size(25, 25);
_tsMain.ResumeLayout(false);
_tsMain.PerformLayout();
ResumeLayout(false);
PerformLayout();
}
void bButton_Click(object sender, EventArgs e)
{
if (Click != null)
{
Click(this, e);
}
}
void bButton_DoubleClick(object sender, EventArgs e)
{
if(DoubleClick != null)
{
DoubleClick(this, e);
}
}
public class ImageButtonToolStripSystemRenderer : ToolStripSystemRenderer
{
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
//base.OnRenderToolStripBorder(e);
}
}
}
}