C# - ListView won't refresh from different form - c#

// PaddlerList (Form 1)
public void RefreshListView()
{
PaddlerListView.Items.Clear();
PaddlerToList();
PaddlerListView.Refresh();
Console.WriteLine("Refresh....");
}
public void PaddlerToList() // Just adds
{
for (int i = 1; i < Main.paddlerList.Count(); i++) // Repeats for all
{
string[] array = new string[4];
ListViewItem item;
array[0] = Main.paddlerList[i].FirstName.ToString();
array[1] = Main.paddlerList[i].LastName.ToString();
array[2] = Main.paddlerList[i].Weight.ToString();
array[3] = Main.paddlerList[i].PreferredSide.ToString();
item = new ListViewItem(array);
PaddlerListView.Items.Add(item);
}
}
private void RefreshList_button_Click(object sender, EventArgs e)
{
RefreshListView();
}
// NewPaddler (Form 2)
private void SubmitPaddler_button_Click(object sender, EventArgs e)
{
// Code here
PaddlerList ListViewRefresh = new PaddlerList(); // Creates an instant of the other form, so it can run the procedure
ListViewRefresh.RefreshListView();
}
When a new paddler is added (the submit button is pressed), the console outputs "Refresh...." showing that the function has been run, but the ListView doesn't refresh
However, when I set a button on the same form as the ListView, it does refresh the ListView with the new items, when the button is pressed.
I can't work out what the issue is here? I think it's something to do with protection levels of the ListView.
Thanks!

When a new PaddlerList object is created, all member variables, like in your case, Items, recieve a fresh start. I think you need to pass the original PaddlerList to your second form in order to actualize the correct form.

I found a solution:
New Paddler Form
// NewPaddler Form
PaddlerList ListObject_global = null;
public NewPaddler(PaddlerList PaddlerList_Object)
{
InitializeComponent();
FormBorderStyle = FormBorderStyle.FixedDialog;
ListObject_global = PaddlerList_Object;
}
if (ListObject_global != null)
{
ListObject_global.RefreshListView(); // Runs function in PaddlerList
}
Paddler List Form
// PaddlerList Form
public void RefreshListView()
{
PaddlerToList();
PaddlerListView.Refresh();
Console.WriteLine("Refresh....");
}

Related

How to access the data grid inside a custom control?

I'm a newbie and I decided to enhance my program's GUI using Krypton Toolkit.
I was able to load it into my project.
The issue that I have created a control with name mycontrol which have a KryptonDataGridView with name mydatagrid.
In my form, I have the following code:
public partial class Form1 : KryptonForm
{
private KryptonPage[] mycontrolpage;
private Control mycontrolcontent;
public Form1()
{
InitializeComponent();
}
private KryptonPage NewmycontrolPage()
{
mycontrolcontent = new mycontrol();
KryptonPage page = new KryptonPage("mypage", null, "OS mypage");
// Add the control for display inside the page
mycontrolcontent.Dock = DockStyle.Fill;
page.Controls.Add(mycontrolcontent);
// Document pages cannot be docked or auto hidden
page.ClearFlags(KryptonPageFlags.DockingAllowAutoHidden | KryptonPageFlags.DockingAllowDocked);
return page;
}
private void Form1_Load(object sender, EventArgs e)
{
// Setup docking functionality
KryptonDockingWorkspace w = kryptonDockingManager.ManageWorkspace(kryptonDockableWorkspace);
kryptonDockingManager.ManageControl(kryptonPanel, w);
kryptonDockingManager.ManageFloating(this);
mycontrolpage = new KryptonPage[] { NewmycontrolPage() };
kryptonDockingManager.AddToWorkspace("Workspace", mycontrolpage);
}
}
My problem is how to access the grid in mycontrol?
Without some code, You could always view the Examples..
Or
Some code snippets:
internal ComponentFactory.Krypton.Toolkit.KryptonDataGridView dgvRules;
Then...
int offset = dgvRules.Rows.Add((bool)condition, name, description, applied);
KryptonDataGridViewCheckBoxCell dataGridViewCell = dgvRules.Rows[offset].Cells[0] as KryptonDataGridViewCheckBoxCell;
if (condition == Tribool.Unknown
|| accumulationRules[offset] == Tribool.Unknown)
{
dataGridViewCell.ReadOnly = condition == Tribool.Unknown;
dataGridViewCell.ThreeState = true;
dataGridViewCell.Value = CheckState.Indeterminate;
}
else
{
dataGridViewCell.Value = (CheckState)accumulationRules[offset];
}

Add dynamically added textbox value from User Control to main form

In my main form I have a textbox namely textBoxTotalTotal and I want all the dynamically added textbox to be the added/sum in my textBoxTotalTotal How can I achieve that?
In my main form I have this:
textBoxTotalTotal
Then in my User Control I have this
public void textBoxTranspo_TextChanged(object sender, EventArgs e)
{
int intTranspo = 0, intBoxDaily = 0;
if (int.TryParse(textBoxTranspo.Text, out intTranspo) && int.TryParse(textBoxDaily.Text, out intBoxDaily))
textBoxTotalAmount.Text = (intTranspo + intBoxDaily).ToString();
}
and
public void textBoxDaily_TextChanged(object sender, EventArgs e)
{
int intTranspo = 0, intBoxDaily = 0;
if (int.TryParse(textBoxTranspo.Text, out intTranspo) && int.TryParse(textBoxDaily.Text, out intBoxDaily))
textBoxTotalAmount.Text = (intTranspo + intBoxDaily).ToString();
}
Note that I am dynamically adding that User Control via button in the main form as many times I like. So the textBoxTotalTotal should just add them up wheter a new 2 textbox comes up.
Assuming that UserControls' Parent is Form1 and User Control type MyUserControl:
(You should set the correct parent, and user control type)
MyUserControl[] controls = Form1.Controls.OfType<MyUserControl>().ToArray();
int Total = 0;
for(int i=0;i<controls.Length;i++){
controls[i].Controls.OfType<TextBox>().ToList()
.ForEach(txt => Total += int.Parse(txt.Text));
}
If you are doing it from the UserControl itself then:
MyUserControl[] controls = Parent.Controls.OfType<MyUserControl>().ToArray();
int Total = 0;
for(int i=0;i<controls.Length;i++){
controls[i].Controls.OfType<TextBox>().ToList()
.ForEach(txt => Total += int.Parse(txt.Text));
}

C# dynamic data display - update LineGraph

In my XAML file, I create a ChartPlotter then I create in c# my LineGraphs and attatch them to my ChartPlotter. I tried to find a way to update these LineGraphs after their creation, but it always failed.
The only solution I found, is that I delete all LineGraphs , re-create them with new values and finally link them to my ChartPlotter.
How can I update LineGraph ?
for (int i = 0; i < lgs.Length; i++)
if (lgs[i] != null)
lgs[i].RemoveFromPlotter();
PS : lgs is my LineGraph array.
To update your LineGraphs, you have to use the ObservableDataSource object instead of the CompositeDataSource. With this object, you can use the method AppendAsync().
public partial class MainWindow : Window
{
public ObservableDataSource<Point> source1 = null;
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// Create source
source1 = new ObservableDataSource<Point>();
// Set identity mapping of point in collection to point on plot
source1.SetXYMapping(p => p);
// Add the graph. Colors are not specified and chosen random
plotter.AddLineGraph(source1, 2, "Data row");
// Force everyting to fit in view
plotter.Viewport.FitToView();
// Start computation process in second thread
Thread simThread = new Thread(new ThreadStart(Simulation));
simThread.IsBackground = true;
simThread.Start();
}
private void Simulation()
{
int i = 0;
while (true)
{
Point p1 = new Point(i * i, i);
source1.AppendAsync(Dispatcher, p1);
i++;
Thread.Sleep(1000);
}
}
}
All you want is in the while of the method Simulation.
source1.AppendAsync(Dispatcher, p1);

Switching Panels via Index Methods

I've been trying to solve my issue for quite a while and to be honest am getting nowhere. What i would like is when the user clicks the 'top' button on my panel it automatically goes to the top( and swaps with the one there.) and when they click the bottom button it automatically goes to the bottom. I'm setting the index panel manually but of course this doesnt work because its only viable for one panel (i have ten). Greatly appreciate some help in finding a method that can send the panel to the top of the stack regardless of its position.
Here is a image (basic) to help understand
Control ctrlToMove = (Control)this.bookControls[bookName];
int ctrlToMoveIndex = bookPanel.Controls.IndexOf(ctrlToMove);
int ctrlToSwapIndex = ctrlToMoveIndex - 5;
Control ctrlToSwap = bookPanel.Controls[ctrlToSwapIndex];
this.bookPanel.Controls.SetChildIndex(ctrlToMove, ctrlToSwapIndex);
this.bookPanel.Controls.SetChildIndex(ctrlToSwap, ctrlToMoveIndex);
Based on your drawing, I made a UserControl with a button on it:
void uc_ButtonClicked(object sender, EventArgs e) {
UserControl1 uc = sender as UserControl1;
if (uc != null) {
int childIndex = flowLayoutPanel1.Controls.GetChildIndex(uc);
if (childIndex > 0) {
UserControl1 ucTop = flowLayoutPanel1.Controls[0] as UserControl1;
flowLayoutPanel1.Controls.SetChildIndex(uc, 0);
flowLayoutPanel1.Controls.SetChildIndex(ucTop, childIndex);
}
}
}
According to your picture you have one control per row in panel. Thus I suggest you to use TableLayoutPanel instead of FlowLayoutPanel. Also I'd create user control for items in panel. E.g. it will have name PriorityUserControl and four buttons to increase, decrease, maximize, minimize it's 'priority' (I placed buttons horizontally just to save place on screen):
Next, create four events in this user control:
public event EventHandler PriorityMaximized;
public event EventHandler PriorityIncreased;
public event EventHandler PriorityDecreased;
public event EventHandler PriorityMinimized;
And rise appropriate event when button clicked:
private void topButton_Click(object sender, EventArgs e)
{
if (PriorityMaximized != null)
PriorityMaximized(this, EventArgs.Empty);
}
That's it. We have user control which tells whether it want to move up or down. Now add user controls to TableLayoutPanel (either manually or dynamically) and subscribe same event handlers of these four events to ALL user controls. Something like:
// create user control and attach event handlers
PriorityUserControl control = new PriorityUserControl();
control.PriorityMaximized += priorityUserControl_PriorityMaximized;
control.PriorityMinimized += priorityUserControl_PriorityMinimized;
control.PriorityIncreased += priorityUserControl_PriorityIncreased;
control.PriorityDecreased += priorityUserControl_PriorityDecreased;
// add another row to table
panel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
panel.RowCount = panel.RowStyles.Count;
// add control table layout panel
panel.Controls.Add(control);
panel.SetRow(control, panel.RowCount - 1);
Good. All you should do now is implement these event handlers. It's simple. E.g. decreasing priority (i.e. moving down):
private void priorityUserControl_PriorityDecreased(object sender, EventArgs e)
{
// sender is a control where you clicked Down button
Control currentControl = (Control)sender;
// get position in panel
var position = panel.GetPositionFromControl(currentControl);
// just to be sure control is not one at the bottom
if (position.Row == panel.RowCount - 1)
return;
// we want to switch with control beneath current
Control controlToSwitch = panel.GetControlFromPosition(0, position.Row + 1);
// move both controls
panel.SetRow(currentControl, position.Row + 1);
panel.SetRow(controlToSwitch, position.Row);
}
Now implementation of maximizing priority (i.e. moving to top):
private void priorityUserControl_PriorityMaximized(object sender, EventArgs e)
{
Control currentControl = (Control)sender;
var position = panel.GetPositionFromControl(currentControl);
if (position.Row == 0 || panel.RowCount < 2)
return;
Control topControl = panel.GetControlFromPosition(0, 0);
panel.SetRow(currentControl, 0);
panel.SetRow(topControl, position.Row);
}
I believe you will create rest two handlers by yourself.
The key of what you want is setting up a clear and extendable algorithm capable to deal with the different positions of the Panels. Here you have a simple code showing certain approach to this problem:
public partial class Form1 : Form
{
int[] panelLocations;
Point[] pointLocations;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panelLocations = new int[5];
pointLocations = new Point[5];
panelLocations[1] = 1;
panelLocations[2] = 2;
panelLocations[3] = 3;
pointLocations[1] = new Point(panel1.Left, panel1.Top);
pointLocations[2] = new Point(panel2.Left, panel2.Top);
pointLocations[3] = new Point(panel3.Left, panel3.Top);
}
private void relocate(int curPanel, bool goTop)
{
int curLoc = panelLocations[curPanel];
int newLoc = curLoc - 1;
if (!goTop)
{
newLoc = curLoc + 1;
}
if (newLoc < 1) newLoc = 3;
if (newLoc > 3) newLoc = 1;
if (newLoc != curLoc)
{
int otherIndex = Array.IndexOf(panelLocations, newLoc);
panelLocations[curPanel] = newLoc;
relocatePanel(curPanel);
panelLocations[otherIndex] = curLoc;
relocatePanel(otherIndex);
}
}
private void relocatePanel(int curIndex)
{
if (curIndex == 1)
{
panel1.Location = pointLocations[panelLocations[1]];
}
else if (curIndex == 2)
{
panel2.Location = pointLocations[panelLocations[2]];
}
else if (curIndex == 3)
{
panel3.Location = pointLocations[panelLocations[3]];
}
}
private void buttonTop1_Click(object sender, EventArgs e)
{
relocate(1, true);
}
private void buttonBottom1_Click(object sender, EventArgs e)
{
relocate(1, false);
}
}
Open a new project, add 3 panels (Panel1, Panel2 and Panel3... better put different background colors) and include two buttons (buttonUp and buttonDown). This code will make the Panel1 to go up and down (by changing its position with the other panels).
The idea is pretty simple: at the start you store the positions of all the Panels in an array. In another array, you store where each panel is located every time (1 is the original position of Panel1, etc.).
It is a quite simple code which you can improve and extend as much as required, but the idea is pretty reliable and you can use it in any case: a set of fixed positions through which the panels will be moving.

Manage windows inside a panel with a 'Windows'-like menu

I've a panel.
I add WinForms inside it. The WinForms added have the TopLevel and Visible properties set to FALSE and TRUE.
I can do a panel.SetChildIndex(WinForm1,0) to bring WinForm1 to front.
What I've not managed to do is keep a track of the actual ChildIndex of the panel.
The idea is to have buttons that opens forms inside the panel, and that when the panel opens a new button is added in a Windows menu.
Something like when many files are open on a VS Project, you can go to Window menu and select one. Also, if you change the active page by clicking the page, the Window menu auto-updates and checks the actual active page.
I want to do this, but with a panel container. I've managed to get done everithing, but not the the Window menu auto-updates and checks the actual active page part.
Isn't there an event fired when BringToFront() or SetChildIndex(form, index) are called? Any event when I click another form that's inside the panel and it becomes the "active one"? Or some property of the panel that I can keep track of that changes when active form changes?
It is taken from here
When Control's ZOrder is chaged layout operation is always performed
in control's container control.
When I subscribed to container's Layout event and called
BringToFront() it showed me Control that changed its
ZOrder(LayoutEventArgs.AffectedControl) and changed property
(LayoutEventArgs.AffectedProperty).
Found that when a form inside a panel is closed, the Controls property of the panel gets reindexed, where the index zero is the form that gets the new focus. Now that I've a way to check the form that's in front when I close another one, windows administration in panels is done.
Going to put the source code, maybe it can help someone :)
Please note that I'm using a RadRibbonForm, a standard panel, and RadForms inside the panel. Rad's are from Telerik. Some things should change to make this work on standardWinForms, but the changes are minimal.
Also, I'm not using a menu that shows the forms, I'm using RadButtonElement's in a page of the ribbon menu instead.
AddRadFormWindow must be called to put a window and manage it automatically.
Example of adding a window:
AddRadFormWindow(typeof (MyRadForm))
Now, the source. It must be inside the code of the RadRibbonForm's class.
public static class ExtensionsRadForm
{
[DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hWnd, uint msg);
public static void Deminimize(this RadForm form)
{
if (form.WindowState == FormWindowState.Minimized)
ShowWindow(form.Handle, 9);
}
}
private void RefreshButtonsChecks(string windowName)
{
if (windowName != null)
{
principalPanel.Controls[windowName].BringToFront();
}
if (principalPanel.Controls.Count > 0)
{
if (principalPanel.Controls.Cast<RadForm>().Any(radForm => radForm.WindowState != FormWindowState.Minimized))
{
foreach (RadItem item in radRibbonBarGroupOpenWindows.Items)
{
var buttonBorder = ((RadButtonElement) item).BorderElement;
if (item.Name == panelPrincipal.Controls[0].Name + "Button")
{
buttonBorder.ForeColor = Color.LimeGreen;
buttonBorder.BottomColor = Color.LimeGreen;
buttonBorder.TopColor = Color.LimeGreen;
buttonBorder.LeftColor = Color.LimeGreen;
buttonBorder.RightColor = Color.LimeGreen;
principalPanel.Controls[0].Focus();
}
else
{
buttonBorder.ForeColor = Color.Transparent;
buttonBorder.BottomColor = Color.Transparent;
buttonBorder.TopColor = Color.Transparent;
buttonBorder.LeftColor = Color.Transparent;
buttonBorder.RightColor = Color.Transparent;
}
}
}
else
{
foreach (RadItem item in radRibbonBarGroupAbiertas.Items)
{
var buttonBorder = ((RadButtonElement)item).BorderElement;
buttonBorder.ForeColor = Color.Transparent;
buttonBorder.BottomColor = Color.Transparent;
buttonBorder.TopColor = Color.Transparent;
buttonBorder.LeftColor = Color.Transparent;
buttonBorder.RightColor = Color.Transparent;
}
}
}
}
private void PrincipalPanelLayout(object sender, LayoutEventArgs e)
{
RefreshButtonsChecks(null);
}
private void RadButtonElementCloseAllWindowsClick(object sender, EventArgs e)
{
int limitButtons = radRibbonBarGroupOpenWindows.Items.Count;
for (int index = 0; index < limitButtons; index++)
{
RadItem radItem = radRibbonBarGroupOpenWindows.Items[0];
radItem.Dispose();
}
int limitControls = principalPanel.Controls.Count;
for (int index = 0; index < limitControls; index++)
{
Control control = principalPanel.Controls[0];
control.Dispose();
}
Update();
GC.Collect();
}
private void AddRadFormWindow(Type windowToAdd)
{
if (!principalPanel.Controls.ContainsKey(windowToAdd.Name))
{
var window = (RadForm) Activator.CreateInstance(windowToAdd);
window.TopLevel = false;
window.Visible = true;
window.FormClosing += (method, args) =>
{
radRibbonBarGroupOpenWindows.Items[window.Name + "Button"].Dispose();
GC.Collect();
};
window.Enter += (method, args) => RefreshButtonsChecks(window.Name);
var closeMenuItem = new RadMenuItem("Close");
closeMenuItem.MouseDown += (method, args) =>
{
panelPrincipal.Controls[window.Name].Dispose();
radRibbonBarGroupOpenWindows.Items[window.Name + "Button"].Dispose();
};
var contextMenu = new RadContextMenu();
contextMenu.Items.Add(closeMenuItem);
var button = new RadButtonElement(window.Text) {Name = window.Name + "Button"};
button.MouseDown += (method, args) =>
{
switch (args.Button)
{
case MouseButtons.Left:
if (((RadForm) principalPanel.Controls[window.Name]).WindowState ==
FormWindowState.Minimized)
((RadForm) principalPanel.Controls[window.Name]).Deminimize();
principalPanel.Controls[window.Name].BringToFront();
principalPanel.Controls[window.Name].Focus();
break;
case MouseButtons.Right:
contextMenu.Show(MousePosition);
break;
}
};
radRibbonBarGroupOpenWindows.Items.Add(button);
principalPanel.Controls.Add(window);
principalPanel.Controls[window.Name].BringToFront();
principalPanel.Controls[window.Name].Focus();
}
principalPanel.Controls[windowToAdd.Name].BringToFront();
principalPanel.Controls[windowToAdd.Name].Focus();
Update();
GC.Collect();
}
public Constructor()
{
panelPrincipal.Layout += PanelPrincipalLayout;
}

Categories