I used this http://www.devexpress.com/Support/Center/p/Q233111.aspx (the code is in VB so I converted it to C#) to get vertical column headers. I get the vertical headers but my problem is some of them doesn't fit, so they are not fully visible.
Is it possible to autoheight the column headers ? (all height set to max height)
As shown in Devexpress support center i think this will be the solution to your problem
First add an helper class to your solution
public class AutoHeightHelper
{
GridView view;
public AutoHeightHelper(GridView view)
{
this.view = view;
EnableColumnPanelAutoHeight();
}
public void EnableColumnPanelAutoHeight()
{
SetColumnPanelHeight();
SubscribeToEvents();
}
private void SubscribeToEvents()
{
view.ColumnWidthChanged += OnColumnWidthChanged;
view.GridControl.Resize += OnGridControlResize;
view.EndSorting += OnGridColumnEndSorting;
}
void OnGridColumnEndSorting(object sender, EventArgs e)
{
view.GridControl.BeginInvoke(new MethodInvoker(SetColumnPanelHeight));
}
void OnGridControlResize(object sender, EventArgs e)
{
SetColumnPanelHeight();
}
void OnColumnWidthChanged(object sender, DevExpress.XtraGrid.Views.Base.ColumnEventArgs e)
{
SetColumnPanelHeight();
}
private void SetColumnPanelHeight()
{
GridViewInfo viewInfo = view.GetViewInfo() as GridViewInfo;
int height = 0;
for (int i = 0; i < view.VisibleColumns.Count; i++)
height = Math.Max(GetColumnBestHeight(viewInfo, view.VisibleColumns[i]), height);
view.ColumnPanelRowHeight = height;
}
private int GetColumnBestHeight(GridViewInfo viewInfo, GridColumn column)
{
GridColumnInfoArgs ex = viewInfo.ColumnsInfo[column];
GraphicsInfo grInfo = new GraphicsInfo();
grInfo.AddGraphics(null);
ex.Cache = grInfo.Cache;
bool canDrawMore = true;
Size captionSize = CalcCaptionTextSize(grInfo.Cache, ex as HeaderObjectInfoArgs, column.GetCaption());
Size res = ex.InnerElements.CalcMinSize(grInfo.Graphics, ref canDrawMore);
res.Height = Math.Max(res.Height, captionSize.Height);
res.Width += captionSize.Width;
res = viewInfo.Painter.ElementsPainter.Column.CalcBoundsByClientRectangle(ex, new Rectangle(Point.Empty, res)).Size;
grInfo.ReleaseGraphics();
return res.Height;
}
Size CalcCaptionTextSize(GraphicsCache cache, HeaderObjectInfoArgs ee, string caption)
{
Size captionSize = ee.Appearance.CalcTextSize(cache, caption, ee.CaptionRect.Width).ToSize();
captionSize.Height++; captionSize.Width++;
return captionSize;
}
public void DisableColumnPanelAutoHeight()
{
UnsubscribeFromEvents();
}
private void UnsubscribeFromEvents()
{
view.ColumnWidthChanged -= OnColumnWidthChanged;
view.GridControl.Resize -= OnGridControlResize;
view.EndSorting -= OnGridColumnEndSorting;
}
}
Then on your form you should make the helper class to Handle GridView's columns resize events by adding the following lines of code
AutoHeightHelper helper;
private void OnFormLoad(object sender, EventArgs e)
{
helper = new AutoHeightHelper(gridView1);
helper.EnableColumnPanelAutoHeight();
}
private void OnFormClosing(object sender, FormClosingEventArgs e)
{
helper.DisableColumnPanelAutoHeight();
}
Hope this helps...
Related
When I opened the game launcher, I noticed how the news was implemented there.
And I really liked this idea, so I decided to do it in my project, first of all I made a panel, stuffed a few images into it, and then actually made two buttons with which I plan to flip through the images. BUT how to do it smoothly? Here is where the problem is, I do not understand how to make a smooth flipping of
the image
I can't tell how the images are sliding, flipping, stretching or whatever, but I think WinForms with GDI+ isn't the best choice. I think WPF would be better. I would also recommend using a suitable library for those kind of image manipulations.
However, if you want it very(!) simple you could use this class:
public class SlideAnimation
{
public event EventHandler<AnimationEventArgs> AnimationFinished;
private readonly Control Control;
private readonly Timer Timer;
private float fromXPosition;
public SlideAnimation(Control ctrl)
{
Control = ctrl;
Timer = new Timer();
Timer.Interval = 10;
Timer.Tick += Timer_Tick;
Control.Paint += Control_Paint;
}
public float Speed { get; set; }
public Image From { get; set; }
public Image To { get; set; }
public AnimationDirection Direction { get; set; }
public bool IsRunning
{
get
{
return Timer.Enabled;
}
}
public void StartAnimation()
{
// maybe move those checks into the setter of the corresponding property
if (this.From == null)
throw new InvalidOperationException();
if (this.To == null)
throw new InvalidOperationException();
if (this.Speed <= 0)
throw new InvalidOperationException();
fromXPosition = 0;
Timer.Enabled = true;
}
protected void OnAnimationFinished(AnimationEventArgs e)
{
AnimationFinished?.Invoke(this, e);
}
private void Timer_Tick(object sender, EventArgs e)
{
// increase or decrease the position of the first image
fromXPosition = fromXPosition + (this.Speed * this.Direction);
Control.Invalidate();
if (Math.Abs(fromXPosition) >= this.From.Width)
{
Timer.Enabled = false;
OnAnimationFinished(new AnimationEventArgs(this.Direction));
}
}
private void Control_Paint(object sender, PaintEventArgs e)
{
if (!Timer.Enabled)
return;
// draw both images next to each other depending on the direction
e.Graphics.DrawImage(this.From, new PointF(fromXPosition, 0));
e.Graphics.DrawImage(this.To, new PointF(fromXPosition - (this.From.Width * this.Direction), 0));
}
}
public enum AnimationDirection
{
Forward = -1,
Backward = 1
}
public class AnimationEventArgs : EventArgs
{
public AnimationEventArgs(AnimationDirection direction)
{
Direction = direction;
}
public AnimationDirection Direction { get; }
}
This class will only draw the images while the animation is active. Every other invalidation will not trigger the Control_Paint method.
Use following code for your Form:
public class Form1
{
private List<Image> imgList = new List<Image>();
private int currentIndex = 0;
private SlideAnimation animation;
public Slideshow()
{
InitializeComponent();
imgList.Add(Image.FromFile("pic1.bmp"));
imgList.Add(Image.FromFile("pic2.bmp"));
imgList.Add(Image.FromFile("pic3.bmp"));
imgList.Add(Image.FromFile("pic4.bmp"));
imgList.Add(Image.FromFile("pic5.bmp"));
animation = new SlideAnimation(this.Panel1);
animation.Speed = 20;
animation.AnimationFinished += AnimationFinished;
}
private void btnPrev_Click(object sender, EventArgs e)
{
if (currentIndex == 0)
return;
if (animation.IsRunning)
return;
animation.Direction = AnimationDirection.Backward;
animation.From = imgList[currentIndex];
animation.To = imgList[currentIndex - 1];
animation.StartAnimation();
}
private void btnNext_Click(object sender, EventArgs e)
{
if (currentIndex == imgList.Count - 1)
return;
if (animation.IsRunning)
return;
animation.Direction = AnimationDirection.Forward;
animation.From = imgList[currentIndex];
animation.To = imgList[currentIndex + 1];
animation.StartAnimation();
}
private void AnimationFinished(object sender, AnimationEventArgs e)
{
currentIndex = currentIndex - (1 * e.Direction);
}
private void Panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(imgList[currentIndex], 0, 0);
}
}
Since there are a lot of drawing operations you may use a panel which supports DoubleBuffer.
public class DoubleBufferedPanel : Panel
{
public DoubleBufferedPanel()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
}
}
Keep in mind that this example is very simple and far from "fancy".
After I created a userControl and established it in a Windows form, this form could no longer be saved. When I press Ctrl + S or the Save button nothing happens, the small * on the form file name suggests that it was not saved. Also, my form contains a property for a color. When I change this, the color doesn't change and the property window doesn't seem to respond anymore.
Code of custom userControl
namespace FlowGui
{
public partial class FlowProgressBar: UserControl
{
// Public Variables with Setters
private int maxValue;
[Bindable(true), Category("Behavior")]
public int Maximum
{
get
{
return maxValue;
}
set
{
maxValue = value;
DrawBar();
}
}
private int minValue;
[Bindable(true), Category("Behavior")]
public int Minimum
{
get
{
return minValue;
}
set
{
minValue = value;
DrawBar();
}
}
private int currentValue;
[Bindable(true), Category("Behavior")]
public int Value
{
get
{
return currentValue;
}
set
{
currentValue = value;
DrawBar();
}
}
private Color barColor;
[Bindable(true), Category("Appearance")]
public Color BarColor
{
get
{
return barColor;
}
set
{
barColor = value;
CreateBarImage();
DrawBar();
}
}
// private Values for Drawing
private Image canvas;
private Graphics gfx;
private Bitmap barImage;
public FlowProgressBar()
{
InitializeComponent();
}
// Load
private void FlowProgressBar_Load(object sender, EventArgs e)
{
maxValue = 100;
minValue = 0;
currentValue = 0;
barColor = Color.LightBlue;
// Init Graphic
InitGraphics();
CreateBarImage();
DrawBar();
}
private void CreateBarImage()
{
barImage = new Bitmap(10, 50);
Bitmap currentBarImage = Properties.Resources.BarImage_Basic;
for(int x=0; x<10; x++)
{
for (int y = 0; y < 50; y++)
{
Color barPreColor = currentBarImage.GetPixel(x, y);
int r = barPreColor.R * barColor.R / 255;
int g = barPreColor.G * barColor.G / 255;
int b = barPreColor.B * barColor.B / 255;
Color pixelColor = Color.FromArgb(r,g,b);
currentBarImage.SetPixel(x, y, pixelColor);
}
}
}
private void InitGraphics()
{
canvas = new Bitmap(pictureBoxBar.Width, pictureBoxBar.Height);
gfx = Graphics.FromImage(canvas);
}
private void DrawBar()
{
int barWidth = pictureBoxBar.Width;
int barHeight = pictureBoxBar.Height;
Image bgImage = Properties.Resources.BarBG_Raised_Grey;
gfx.DrawImage(bgImage,-200,0,barWidth+400,barHeight);
gfx.DrawImage(barImage, 0, 0, 100, barHeight);
pictureBoxBar.Image = canvas;
}
// Behaviour
private void FlowProgressBar_SizeChanged(object sender, EventArgs e)
{
InitGraphics();
DrawBar();
}
private void pictureBoxBar_Paint(object sender, PaintEventArgs e)
{
InitGraphics();
DrawBar();
}
}
}
My first thought was that it could be because the userControll is in another project and only linked. But even after I implemented the userControll in the main project, my described problems occurred. So I undo this.
I have no idea what I'm doing wrong. Thank you very much for your help.
Solved!
The problem was the pictureBoxBar_Paint() event. After I removed it from the userControl everything runs.
I'm creating a custom FAB button for both android and iOS platforms using Xamarin.Forms.
Everything is working fine, but now I want to be able to somehow receive scrolled events from the nearest parent of the FAB button if any, so I will be able to hide the FAB button when the user is scrolling and then show it again after 2 seconds of scrolling finished?.
The parent could be a plain ScrollView item, or it could be a ListView.
Can this be achieved via the same custom renderers for each platform? Or, can this even be achieved at all?
This is what I did so far:
FabButton class:
public partial class FabButton : Button
{
public static BindableProperty ButtonColorProperty = BindableProperty.Create(nameof(ButtonColor), typeof(Color), typeof(FabButton), Color.Accent);
public Color ButtonColor
{
get => (Color)GetValue(ButtonColorProperty);
set => SetValue(ButtonColorProperty, value);
}
public FabButton()
{
InitializeComponent();
}
}
iOS custom renderer:
public class FabButtonRenderer:ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if(e.NewElement == null)
return;
if (Element.WidthRequest <= 0)
Element.WidthRequest = 60;
if (Element.HeightRequest <= 0)
Element.HeightRequest = 60;
if (Element.Margin == new Thickness(0, 0, 0, 0))
Element.Margin = new Thickness(0, 0, 20, 20);
Element.CornerRadius = (int) Element.WidthRequest / 2;
Element.BorderWidth = 0;
Element.Text = null;
Control.BackgroundColor = ((FabButton) Element).ButtonColor.ToUIColor();
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
Layer.ShadowRadius = 0.2f;
Layer.ShadowColor = UIColor.Black.CGColor;
Layer.ShadowOffset = new CGSize(1, 1);
Layer.ShadowOpacity = 0.80f;
Layer.ShadowPath = UIBezierPath.FromOval(Layer.Bounds).CGPath;
Layer.MasksToBounds = false;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == nameof(FabButton.ButtonColor))
Control.BackgroundColor = ((FabButton) Element).ButtonColor.ToUIColor();
}
}
android custom renderer:
public class FabButtonRenderer: Xamarin.Forms.Platform.Android.AppCompat.ViewRenderer<FabButton,FloatingActionButton>
{
public static void InitRenderer() { }
public FabButtonRenderer(Context context):base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<FabButton> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
if (e.NewElement.HeightRequest <= 0)
e.NewElement.HeightRequest = 85;
if (e.NewElement.WidthRequest <= 0)
e.NewElement.WidthRequest = 75;
if (e.NewElement.Margin.Equals(new Thickness(0, 0, 0, 0)))
e.NewElement.Margin = new Thickness(0, 0, 5, 10);
var fabButton = new FloatingActionButton(Context);
ViewCompat.SetBackgroundTintList(fabButton, ColorStateList.ValueOf(Element.ButtonColor.ToAndroid()));
fabButton.UseCompatPadding = true;
if (!string.IsNullOrEmpty(Element.Image?.File))
fabButton.SetImageDrawable(Context.GetDrawable(Element.Image.File));
fabButton.Click += FabButton_Clicked;
SetNativeControl(fabButton);
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
Control.BringToFront();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Element.ButtonColor))
ViewCompat.SetBackgroundTintList(Control, ColorStateList.ValueOf(Element.ButtonColor.ToAndroid()));
if (e.PropertyName == nameof(Element.Image))
{
if (!string.IsNullOrEmpty(Element.Image?.File))
Control.SetImageDrawable(Context.GetDrawable(Element.Image.File));
}
base.OnElementPropertyChanged(sender, e);
}
public void FabButton_Clicked(object sender, EventArgs e)
{
Element.SendClicked();
}
}
I think Scrollview's "Scrolled" event can help you , you will get X & Y axis values , based on it you have to hide your fab button while it's scrolling.
And for it after 2 seconds you can use "Device.StartTimer" .
Unfortunately, there is no built-in way to do this.Since in my case, the Floating Action Button might be affected by ScrollView control scrolling, or a list view control scrolling, or others.The only way for me to do this that I can think of is to specify explicitly to which ScrollView control the Floating Action Button should be connected, and since this will be a troublesome to implement when the Floating Action Button should be connected to a list view ScrollView and since it's better to use the MVVM pattern, I have find a simpler way to this.
First I declared an interface IFloatingActionButtonHost:
public interface IFloatingActionButtonHost
{
bool ShouldBeHiddenWhenScrolling { get; }
event Action LinkedScrollViewScrolled;
}
And then, I declared a BindableProperty inside the FabButton control like this:
public static BindableProperty ButtonHostProperty = BindableProperty.Create(nameof(ButtonHost), typeof(IFloatingActionButtonHost), typeof(FabButton));
public IFloatingActionButtonHost ButtonHost
{
get => (IFloatingActionButtonHost)GetValue(ButtonHostProperty);
set => SetValue(ButtonHostProperty, value);
}
And in the Renderer for example, on iOS renderer, I checked for this property if it's not null, and if the Floating Action Button should be hidden when the target ScrollView get scrolled or not and then subscribed to the event in the interface.
var fabButton = (FabButton)Element;
if (fabButton.ButtonHost != null && fabButton.ButtonHost.ShouldBeHiddenWhenScrolling)
{
fabButton.ButtonHost.LinkedScrollViewScrolled += OnLinkedScrollView_Scrolled;
}
And then I handled the event in the renderer:
private void OnLinkedScrollView_Scrolled()
{
Element.IsVisible = false;
Device.StartTimer(TimeSpan.FromSeconds(3), () =>
{
if(Element != null){
Element.IsVisible = true;
}
return false;
});
}
The OnElementPropertyChanged implementation should be changed as well.
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == nameof(FabButton.ButtonColor))
Control.BackgroundColor = ((FabButton) Element).ButtonColor.ToUIColor();
else if(e.PropertyName == nameof(FabButton.ButtonHost)){
var fabButton = (FabButton)Element;
if (fabButton.ButtonHost != null && fabButton.ButtonHost.ShouldBeHiddenWhenScrolling)
{
fabButton.ButtonHost.LinkedScrollViewScrolled += OnLinkedScrollView_Scrolled;
}
}
}
On Each page code-behind, I make the page inherit form this interface, and just passed the page instance to the target ViewModel.
P.S. For ListView I had to write a custom renderer to expose the Scrolled event. Sorry, I haven't find a better way to do this.
This is my attempt to solve this problem, if you have a better solution, please just write another answer to this question and I will mark it as the best answer.
I have 2 labels and a property in user control:
Here is property:
private int _SelectIndex;
[Browsable(true)]
public int SelectIndex { get; set; }
and 2 labels:
Label lbl1, lbl2;
void iControl()
{
lbl1 = new Label();
lbl2 = new Label();
lbl1.Name = "lbl1";
lbl2.Name = "lbl2";
lbl1.Click += lbl_Click;
lbl2.Click += lbl_Click;
this.Controls.Add(lbl1);
this.Controls.Add(lbl2);
}
Click:
void lbl_Click(object sender, EventArgs e)
{
Label selectedlbl = sender as Label;
if(selectedlbl.Name == "lbl1")
this.Select = 1;
else
this.Select = 2;
}
Class Event:
public class SelectEventArgs : EventArgs
{
private int index;
public SelectEventArgs(int index)
{
this.index = index;
}
public int ItemIndex
{
get
{
return index;
}
}
}
Custom event in my control:
public event EventHandler SelectEvent;
protected virtual void OnSelectEvent()
{
if (SelectEvent!= null)
SelectEvent(this, new SelectEventArgs(this._SelectIndex));
}
I need an event to get and set property value in MainForm as following:
int index = 0;
public Form1()
{
InitializeComponent();
this.icontrol = new iControl();
this.SelectEvent += Select();
}
void Select(object sender, SelectItem e)
{
//use this to set value of Select
this.icontrol.SelectIndex = index;
//and this to get value of Select
index = this.icontrol.SelectIndex;
}
Select is empty.
How to get it to work?
I post here for any one need it:
1.Declare a delegate:
public delegate void SelectIndexEventHandler(object sender, SelectEventArgs e);
public class SelectEventArgs : EventArgs
{
private int index;
public SelectEventArgs(int index)
{
this.index = index;
}
public int ItemIndex
{
get { return index; }
set { index = value; }
}
}
2. declare an event SelectIndexChanged and a method OnSelectIndexChanged:
public event SelectIndexEventHandler SelectIndexChanged;
protected virtual void OnSelectIndexChanged(SelectEventArgs e)
{
if (SelectIndexChanged != null)
SelectIndexChanged(this, e);
}
3.Call it in setter:
public int SelectIndex
{
get { return _SelectIndex; }
set {
_SelectIndex = value;
OnSelectIndexChanged(new SelectEventArgs(value));
}
}
and then MainForm:
this.gListBox1.SelectIndexChanged += icontrol_SelectIndexChanged;
void icontrol_SelectIndexChanged(object sender, SelectEventArgs e)
{
var current = e.ItemIndex;
}
thank again jbmintjb Reza Aghaei.
The code has multiple issues. Consider these tips to solve the issues:
SelecetEvent does't belong to the Form. The event belongs to icontrol.
this.SelectEvent += Select(); is incorrect, you should use:
icontrol.SelectEvent += Select;
When you have a custom event args, you should define the event this way:
public event EventHandler<SelectEventArgs> SelectEvent;
You should raise the event in setter of your property, using OnSelectEvent method which you created.
To learn more about events take a look at C# Handling and Raising Events.
Take a look at the SelectedIndexChanged event on the listbox control, think that is what you are looking for
I would like to implement a functionality similar to jQuery TagIt into C# windows forms.
Here is the link for jQuery - http://aehlke.github.com/tag-it/
I am thinking of creating a user control for this functionality.
Any help on how to go about this?
You're in luck, as there's already a container control called a FlowLayoutPanel that will get you 90% of the way there as a flowing tag host.
FlowLayoutPanel Class # MSDN
This control is available from the Toolbox in Visual Studio, so a good starting point would be to make a custom control based upon a FlowLayoutPanel, and another custom control to represent a tag based upon a Label or Checkbox, and update the drawing and behavior (in the case of a Label) to respond to clicks and to display the [x] to dismiss the tag.
Label Class # MSDN
CheckBox Class # MSDN
After making these two controls, you will need to do additional work to make your FlowLayoutPanel-derived control add/remove Label-based controls representing the state of the tags present.
Update: One thing I missed, a TextBox or other input field would need to be added in place to support adding new tags.
TextBox # MSDN
public class TagLayoutPanel : FlowLayoutPanel
{
//local variables/controls
private TextBox _entryBox;
private Dictionary<string,string> _currentTags;
//events
public delegate void TagsUpdatedHandler(TagEventArgs e);
public event TagsUpdatedHandler TagsUpdated;
//constructor(s)
public TagLayoutPanel()
{
Init();
}
public List<string> GetCurrentTags()
{
var lst = new List<string>();
if (_currentTags != null)
lst = _currentTags.Keys.ToList();
return lst;
}
private void Init()
{
_currentTags = new Dictionary<string, string>();
//Entry box
this.Padding = new Padding(3);
this.BackColor = Color.White;
_entryBox = new TextBox();
_entryBox.BackColor = Color.White;
_entryBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
_entryBox.KeyUp += _entryBox_KeyUp;
this.Controls.Add(_entryBox);
}
private void _entryBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
var tag = _entryBox.Text;
if (!string.IsNullOrEmpty(tag))
{
this.AddTag(tag);
_entryBox.Text = String.Empty;
}
}
}
protected override void OnGotFocus(EventArgs e)
{
//Set focus to the textentry box.
base.OnGotFocus(e);
this._entryBox.Focus();
}
public void AddTag(string tag)
{
bool added = false;
if (!_currentTags.ContainsKey(tag))
{
_currentTags.Add(tag, tag);
added = true;
}
if(added)
{
Redraw();
Notify();
}
}
private void Notify()
{
if(TagsUpdated != null)
TagsUpdated(new TagEventArgs(GetCurrentTags().ToArray()));
}
public void Redraw()
{
this.Controls.Clear();
foreach (var tag in _currentTags.Keys)
{
DrawTag(tag);
}
AddEntry();
}
private void AddEntry()
{
this.Controls.Add(_entryBox);
_entryBox.Focus();
}
public void DrawTag(string tag)
{
var lbl = new Label();
lbl.MouseMove += lbl_MouseMove;
lbl.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
lbl.BackColor = Color.LightGray;
lbl.Name = "lbl_" + tag.Replace(" ", "");
lbl.ImageAlign = ContentAlignment.TopRight;
lbl.Text = tag;
lbl.Tag = tag;
lbl.Image = Resources.close_x; //Replace with your own image.
lbl.Click += lbl_Click;
this.Controls.Add(lbl);
}
private void lbl_Click(object sender, EventArgs e)
{
var lbl = (Label)sender;
bool removed = false;
foreach(var item in this.Controls)
{
if(item is Label)
{
if(((Label)item).Tag.ToString() == lbl.Tag.ToString())
{
_currentTags.Remove(lbl.Tag.ToString());
removed = true;
break;
}
}
}
if(removed)
{
Redraw();
Notify();
}
}
private void lbl_MouseMove(object sender, MouseEventArgs e)
{
var lbl = (Label)sender;
var startImgX = lbl.Width - 20;
var endImgY = lbl.Height - 15;
if (e.X >= startImgX && e.Y <= endImgY)
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Hand;
else
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Arrow;
}
}
public class TagEventArgs : EventArgs
{
public string[] Tags { get; private set; }
public TagEventArgs(string[] tags)
{
Tags = tags;
}
}