Shift listView tiles? - c#

I have been attempting to understand the tiled listView in c#.net for weeks now with no succession.
I have shrunk my form's height/width (154x154) to the same tile size as the picture(s) (items with pictures) in my listView (which is docked in the form2); when my form2 is shown, you see item[0] in the listView...that is it! (which I want so far, so good!)
I have set the scrollable property to false to do away with both scrollbars (works perfectly fine so far...)
I have hooked both the left and right arrow keys GLOBALLY (which works as it has been thoroughly debugged) and when clicking the RIGHT arrow key, it should VERTICALLY bring up item[1], and so fourth.
The LEFT arrow key would bring up the previous item till it hits 0.
I have tried the following, but it does NOTHING.
private void HotkeyHandler(int i)
{
{
if (this.listView1.InvokeRequired)
{
SetHotkeyCallback p = new SetHotkeyCallback(HotkeyHandler);
this.Invoke(p, new object[] { i });
}
else
{
switch (i)
{
case 1:
listView1.View = View.List;
if (listView1.TopItem.Index > 0)
{
listView1.TopItem = listView1.Items[listView1.TopItem.Index - 1];
}
listView1.View = View.Tile;
break;
case 2:
listView1.View = View.List;
if (listView1.TopItem.Index < listView1.Items.Count)
{
listView1.TopItem = listView1.Items[listView1.TopItem.Index + 1];
}
listView1.View = View.Tile;
break;
}
}
}
}
Please help me, I been loosing my mind for weeks now.
EDIT: The switch within the function above does go off, I have debugged it; therefore, it is not the invoking that is the problem...

I don't think you can do it directly.
The way to get rid of the ScrollBars is indeed to set Scrollable = false;.
But that means what it says: Now the ListView will not scroll.
Here is a common workaround for many scrolling issues:
Place the Listview in a Panel and make it as large as needed to show all Items.
Then in order to scroll simply move the LV up and down:
private void prepare_Click_1(object sender, EventArgs e)
{
// we sit inside a Panel
listView1.Parent = panel1;
// initially they have the same size
listView1.Size = panel1.Size;
listView1.Location = Point.Empty;
// a few test items
for (int i = 0; i < 100; i++)
listView1.Items.Add("Item " + i);
// now grow the height to display all items:
int cols = listView1.Width / listView1.TileSize.Width;
listView1.Height = (listView1.Items.Count / cols) * listView1.TileSize.Height;
}
// moving the LV up looks like scrolling down..
private void scrollDown_Click(object sender, EventArgs e)
{
listView1.Top -= listView1.TileSize.Height;
if (listView1.Bottom < panel1.Height)
listView1.Top = -listView1.Height + panel1.Height;
}
// moving the LV down looks like scrolling up..
private void scrollUp_Click_1(object sender, EventArgs e)
{
listView1.Top += listView1.TileSize.Height;
if (listView1.Top > 0) listView1.Top = 0;
}

Related

How to move label's text right to left,when a character hides in left it shows on right?

Here is my key code:
using System;
using System.Windows.Forms;
namespace Scroller
{
public partial class Form1 : Form
{
int i, j;
bool k = false;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = "Time:"+ System.DateTime.Now.ToString();
i--;
j = i + this.Width;
if (i < this.Width && i > 0)
{
label1.Left = i;
}
else
if (i < 0 && k == false)
{
label1.Left = i;
k = true;
}
else
if (i < 0 && k == true)
{
label1.Left = j;
k = false;
}
if (i < 0 - label1.Width)
{
i = this.Width - label1.Width;
}
}
private void Form1_Load(object sender, EventArgs e)
{
label1.Text = "Time:"+ System.DateTime.Now.ToString();
i = this.Width - label1.Width;
label1.Left = i;
}
}
}
The effect that I want to make is the whole time string move right to left. When a pixel of the text disappear on the left side (because it is out of the form's left border),the pixel will shows on the right side.
In other words, the effect can't be make by delete the first character of string and append it to the last.
I knew that it will be easier to use two label to do it. Set one's location in the form and hide the other right by the form. Move them in the same time.
When the first label hit the left border of the form, the second hit the right border of the form. And the first one move out, the second move in. Until the second totally move in, reset their x location.
But I just want to use one label. So I chose to quickly switch the label's location, and try to "cheat" user's eye. The problem is when the label switch between left and right, it flash very obviously. Even though I set timer's interval below 20,the problem still exist.
Could you help me dissolve the flash problem or enlighten me other ways which can just use one label and one timer to make the effect I need?
Thanks. If I didn't describer my problem clear enough or need more code, please let me know.
I don't think you can work out the flashing problem changing the label's location in a windows form.
Another solution would be to set the label width the same size as the form width, make the label text fill all the width using spaces and make the timer always get the last character and put it on the beginning of the string.
Sample code below.
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = label1.Text.Substring(label1.Text.Length - 1) + label1.Text.Remove(label1.Text.Length - 1);
}
private void Form1_Load(object sender, EventArgs e)
{
// The total spaces required to fill the form vary from form.width and the initial label.text.width
// Width | Spaces
// 177 | 13
// 228 | 30
// 297 | 53
// 318 | 60
// The spacesEnd = 60 work for a form with width 319
int spacesBegin = 0, spacesEnd = 60;
label1.Text = "Time:" + System.DateTime.Now.ToString();
label1.AutoSize = false;
label1.Left = -3;
label1.Width = this.Width - 1;
label1.Height = 15;
label1.BorderStyle = BorderStyle.FixedSingle;
for (int i = 0; i < spacesBegin; i++)
label1.Text = " " + label1.Text;
for (int i = 0; i < spacesEnd; i++)
label1.Text += " ";
Timer timer = new Timer();
timer.Tick += timer1_Tick;
timer.Interval = 50;
timer.Start();
}

C# Drag and Drop labels within FlowLayoutPanels

I have small problem. I want make program where I can drag generated labels between multiple FlowLayoutPanels. But last few days I have tried to make drag and drop working. I tried many tutorials, examples etc. but it is always something bit diferent and I am not able extract only basic code.
It is similar to this program but it is in Visual Basic and I need it in C#. I know it is maybe very simple, but I am newbie.
Thank you for help.
Real Drag&Drop ist most useful between applications and maybe also between Forms.
Assuming you want to drag Labels between FLPs on the same Form, the code below should get you going..
It takes two FlowLayoutPanels called FLP1 and FLP2 and starts by initializing them with a few Labels.
Note the three mouse events I add to each Label to emulate a Drag&Drop action!
private void Form1_Load(object sender, EventArgs e)
{
// create a few Label with varying Colors for testing..
fillFLP(FLP1, 88);
fillFLP(FLP2, 111);
}
void fillFLP(FlowLayoutPanel FLP, int cc)
{
for (int i = 0; i < 24; i++)
{
Label l = new Label();
// the next 3 lines optional and only are there for testing!
l.AutoSize = false;
l.Text = FLP.Name + " " + i.ToString("00");
l.BackColor = Color.FromArgb(255, cc * 2 - i, 255 - 5 * i, cc + 5 * i);
// add controls and set mouse events:
FLP.Controls.Add(l);
l.MouseDown += l_MouseDown;
l.MouseMove += l_MouseMove;
l.MouseUp += l_MouseUp;
}
}
// the currently moved Label:
Label mvLabel = null;
void l_MouseDown(object sender, MouseEventArgs e)
{
// keep reference
mvLabel = (Label)sender;
}
void l_MouseMove(object sender, MouseEventArgs e)
{
// if we are dragging a label:
if (mvLabel != null)
{
// mouse pos in window coords
Point mvPoint = this.PointToClient(Control.MousePosition);
// the label is still in the FLP, so we start the drg action:
if (mvLabel.Parent != this)
{
mvLabel.Parent = this;
mvLabel.Location = mvPoint;
mvLabel.BringToFront();
}
else
{
// we are already in the form, so we just move
mvLabel.Location = mvPoint;
}
}
}
void l_MouseUp(object sender, MouseEventArgs e)
{
// are we over a FLP? and if so which?
Point MP = Control.MousePosition;
FlowLayoutPanel FLP = null;
Point mLoc1 = FLP1.PointToClient(MP);
Point mLoc2 = FLP2.PointToClient(MP);
if (FLP1.ClientRectangle.Contains(mLoc1)) FLP = FLP1;
else if (FLP2.ClientRectangle.Contains(mLoc2)) FLP = FLP2;
else return; // no! nothing we can do..
// yes, now find out if we are over a label..
// ..or over an empty area
mvLabel.SendToBack();
Control cc = FLP.GetChildAtPoint(FLP.PointToClient(MP));
// if we are over the FLP we can insert at the beginning or the end:
// int mvIndex = 0; // to the beginning
int mvIndex = FLP.Controls.Count; // to the end
// we are over a Label, so we insert before it:
if (cc != null) mvIndex = FLP.Controls.IndexOf(cc);
// move the Label into the FLP
FLP.Controls.Add(mvLabel);
// move it to the right position:
FLP.Controls.SetChildIndex(mvLabel, mvIndex);
// let go of the reference
mvLabel = null;
}
This lets you drag and drop Lables to and fro between two FLPs and also within the FLPs by dropping onto Labels.
Note that you will need a few extra lines if you want to allow dropping between Labels and still position there..

Change fontSize of ListView with ctrl + mousewheel

I have a ListView (auftraegeView). Of this ListView I whish to change the FontSize of its Items through Ctrl + MouseWheel aka. a simple zoom like in excel or a browser.
In the form's ctor I subscribed my method to the event
this.MouseWheel += scrollZoom;
My EventHandler calculates the new FontHeight and applies it, if it doesn't exceed the bounds. The RowHeight is always kept a little bigger, finally I resize the columns so the zoom also works on the horizontal scale.
private void scrollZoom(object sender, MouseEventArgs e)
{
if(Control.ModifierKeys != Keys.Control)
return;
int currFontHeight = ListViewFontHeight;
int delta = (e.Delta)/120;
int newFontHeight = currFontHeight + delta;
if(newFontHeight < 1 || newFontHeight > 150)
return;
ListViewFontHeight = newFontHeight;
ListViewRowHeight = ListViewFontHeight + 4;
auftraegeView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
}
ListViewFontHeight gets the Font.Height of the first Item. (Value is identical across all Items, so the first is as good as any.)
The set is where the issue seems to be (see below). My idea is that I just go through each Item and change the Font.
private int ListViewFontHeight
{
get { return auftraegeView.Items[0].Font.Height; }
set
{
foreach (ListViewItem line in auftraegeView.Items)
{
line.Font = new Font(line.Font.FontFamily, value);
}
}
}
ISSUE / QUESTION
Regardless of the direction I scroll in, the FontSize only increases till it hits the ceiling. The rest works fine (setting ListViewRowHeight, detecting the event at all,...).
What might be causing this?
Try this:
delta = (e.Delta > 0? 1 : -1);
to be on the safe side for different mouse settings.
This works for me:
float delta = (e.Delta > 0 ? 2f : -2f);
listView1.Font = new Font (listView1.Font.FontFamily, listView1.Font.Size + delta);
Found it myself:
In the ListViewFontHeight - property the get accessor used Item.Font.Height instead of Item.Font.Size
private int ListViewFontHeight
{
get { return (int)auftraegeView.Items[0].Font.Size; } //works now

Problem in removing the controls dynamically

Note : In WinForm
I facing problem in TableLayoutPanel. I adding and removing the control dynamicall using TableLauoutPanel. My problem is, if i remove the control in the middle (ie i added TextBox1, TextBox2 and TextBox3 and now i removed TextBox2) at this time other controls are not resized properlly. When the last control (ie TextBox3 ) is removed, its resizing properlly. I attached my code here. What is the problem?
///HERE tbl is the TableLayoutPanel
private void AddText_Click(object sender, EventArgs e)
{
TextBox txt = new TextBox();
txt.MouseDoubleClick += new MouseEventHandler(txt_MouseDoubleClick);
txt.Multiline = true;
txt.Dock = DockStyle.Fill; NEWADD(txt);
}
private void NEWADD(Control ctrl)
{
tbl.RowCount += 1;
tbl.RowStyles.Add(new RowStyle(SizeType.Percent, 100F / tbl.RowStyles.Count));
tbl.Controls.Add(ctrl, 0, tbl.RowStyles.Count - 1);
foreach (RowStyle row in tbl.RowStyles)
{
row.SizeType = SizeType.Percent;
row.Height = 100F / (tbl.RowStyles.Count);
}
}
private void RemoveControl(Control ctrl)
{
tbl.RowCount -= 1;
tbl.Controls.Remove(ctrl);
tbl.RowStyles.Clear();
for (int i = 0; i < tbl.Controls.Count; i++)
{
tbl.RowStyles.Add(new RowStyle(SizeType.Percent, 100F /( tbl.RowStyles.Count +1)));
}
foreach (RowStyle row in tbl.RowStyles)
{
row.SizeType = SizeType.Percent;
row.Height = 100F / (tbl.RowStyles.Count);
}
tbl.Refresh();
}
void txt_MouseDoubleClick(object sender, MouseEventArgs e)
{
RemoveControl(sender as Control);
}
Can't test it at the moment, but it looks like your problem is the logic for removing the row that the control is in.
tbl.RowCount -= 1
is always going to remove the last row. You need to move through each control that is in a row after the the you want to remove and shift your controls up one row. Maybe something like this...
foreach(Control control in tbl.Controls)
{
if(control.Row > controlToRemove.Row)
control.Row--;
}
Since it looks like you're also trying to dynamically create a new table row for each control, you might do a little better with a FlowLayoutPanel. You should be able to style it to get a similar effect and it will be able to handle "row creation" automatically.

C#: How do you edit items and subitems in a listview?

How do you edit items and subitems in a listview? Let's say I have a listview with 3 columns,and subitems,
Car Brand | Car Name | Car Year
Ford | Mustang | 2000
Dodge | Charger | 2007
How would I Add items like that to listview and how would I edit let's say the Car Name on which ever row by index[] if I needed to edit at runtime at firing of an event?
If you're looking for "in-place" editing of a ListView's contents (specifically the subitems of a ListView in details view mode), you'll need to implement this yourself, or use a third-party control.
By default, the best you can achieve with a "standard" ListView is to set it's LabelEdit property to true to allow the user to edit the text of the first column of the ListView (assuming you want to allow a free-format text edit).
Some examples (including full source-code) of customized ListView's that allow "in-place" editing of sub-items are:
C# Editable ListView
In-place editing of ListView subitems
I use a hidden textbox to edit all the listview items/subitems. The only problem is that the textbox needs to disappear as soon as any event takes place outside the textbox and the listview doesn't trigger the scroll event so if you scroll the listview the textbox will still be visible.
To bypass this problem I created the Scroll event with this overrided listview.
Here is my code, I constantly reuse it so it might be help for someone:
ListViewItem.ListViewSubItem SelectedLSI;
private void listView2_MouseUp(object sender, MouseEventArgs e)
{
ListViewHitTestInfo i = listView2.HitTest(e.X, e.Y);
SelectedLSI = i.SubItem;
if (SelectedLSI == null)
return;
int border = 0;
switch (listView2.BorderStyle)
{
case BorderStyle.FixedSingle:
border = 1;
break;
case BorderStyle.Fixed3D:
border = 2;
break;
}
int CellWidth = SelectedLSI.Bounds.Width;
int CellHeight = SelectedLSI.Bounds.Height;
int CellLeft = border + listView2.Left + i.SubItem.Bounds.Left;
int CellTop =listView2.Top + i.SubItem.Bounds.Top;
// First Column
if (i.SubItem == i.Item.SubItems[0])
CellWidth = listView2.Columns[0].Width;
TxtEdit.Location = new Point(CellLeft, CellTop);
TxtEdit.Size = new Size(CellWidth, CellHeight);
TxtEdit.Visible = true;
TxtEdit.BringToFront();
TxtEdit.Text = i.SubItem.Text;
TxtEdit.Select();
TxtEdit.SelectAll();
}
private void listView2_MouseDown(object sender, MouseEventArgs e)
{
HideTextEditor();
}
private void listView2_Scroll(object sender, EventArgs e)
{
HideTextEditor();
}
private void TxtEdit_Leave(object sender, EventArgs e)
{
HideTextEditor();
}
private void TxtEdit_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
HideTextEditor();
}
private void HideTextEditor()
{
TxtEdit.Visible = false;
if (SelectedLSI != null)
SelectedLSI.Text = TxtEdit.Text;
SelectedLSI = null;
TxtEdit.Text = "";
}
Click the items in the list view.
Add a button that will edit the selected items.
Add the code
try
{
LSTDEDUCTION.SelectedItems[0].SubItems[1].Text = txtcarName.Text;
LSTDEDUCTION.SelectedItems[0].SubItems[0].Text = txtcarBrand.Text;
LSTDEDUCTION.SelectedItems[0].SubItems[2].Text = txtCarName.Text;
}
catch{}
Sorry, don't have enough rep, or would have commented on CraigTP's answer.
I found the solution from the 1st link - C# Editable ListView, quite easy to use. The general idea is to:
identify the SubItem that was selected and overlay a TextBox with the SubItem's text over the SubItem
give this TextBox focus
change SubItem's text to that of TextBox's when TextBox loses focus
What a workaround for a seemingly simple operation :-|
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
li = listView1.GetItemAt(e.X, e.Y);
X = e.X;
Y = e.Y;
}
private void listView1_MouseUp(object sender, MouseEventArgs e)
{
int nStart = X;
int spos = 0;
int epos = listView1.Columns[1].Width;
for (int i = 0; i < listView1.Columns.Count; i++)
{
if (nStart > spos && nStart < epos)
{
subItemSelected = i;
break;
}
spos = epos;
epos += listView1.Columns[i].Width;
}
li.SubItems[subItemSelected].Text = "9";
}

Categories

Resources