|
Thank you Hiller.
I delete this section and it run ok.
LVD
|
|
|
|
|
Hi!
I've a bi-dimensional array of labels (a lot of them) so when I make change properties the render is to slow.
My solution (I thought) was make the panel invisible at the init time and then visible when the job is completed but it's visible before the job is completed! I think my app is multithreaded for default.
using System;
using System.Windows.Forms;
namespace Program
{
public partial class Form1 : Form
{
MySqlConnection cn = new MySqlConnection();
iTextSharp.text.pdf.PdfWriter writer;
const int panelHeight = 730;
const int panelWith = 1070;
private Label[,] lbs = new Label[70,50];
public Form1()
{
InitializeComponent();
initBoard();
}
private void initBoard()
{
panel1.Size = new Size(panelWith, panelHeight);
panel1.Visible = false;
anel1.BackColor = SystemColors.ControlText;
int cc, ff;
for (int c = 0; c < 70; c++)
{
cc = c * 15;
for (int f = 0; f < 50; f++)
{
ff = f * 20;
Label lb = new Label();
lbs[c, f] = lb;
lb.Size = new Size(15, 20);
lb.Font = new System.Drawing.Font(label1.Font.Name, 12, FontStyle.Bold);
lb.Location = new System.Drawing.Point(cc + 10, ff + 10);
lb.Parent = panel1;
lb.ForeColor = Color.WhiteSmoke;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
for (int c = 0; c < 70; c++)
for (int f = 0; f < 50; f++)
lbs[c, f].Text = (f % 10).ToString();
panel1.Visible = true;
}
}
}
Any ideas ?
Of course I'm just starting.... this is not the way I should program
modified 29-Feb-16 12:27pm.
|
|
|
|
|
Pablo Bozzolo wrote: this is not the way I should program Very true, 3500 labels to update is far too many. You need to rethink your design, and what you are trying to achieve with this program.
|
|
|
|
|
Of course I know that I want to do (instead of numbers some characters will be placed) and the number of 3500 is not optional.
I'd like to be able to add an event handler to each label in a future so I don't want to use a Richtext or something different to a bunch of controls.
Maybe I can use a GridView (I've no experience in Visual Studio), ...... I hope it will help because If put vertical scrollbar it freeze the GUI because the high number of controls in the Panel.
The question here is WHY I can see when labels are filled if the Panel is invisible!
|
|
|
|
|
If you tell us your ultimate goal here (why do you think you need 3500 labels?) someone might be able to suggest a way to achieve it in a "less strange" way
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
Ok
3500 characters are the number of characters I need to see at once in my program to do something with them.
modified 29-Feb-16 16:15pm.
|
|
|
|
|
Why not a single multiline-TextBox? You could put some spaces between the characters to give it a table-like appearance. Otherwise a DataGridView.
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
Thank you for your answer
I was thinking too to do something like to comment with a multiline-TextBox, so I think I will decouple things to be able to switch easily.
|
|
|
|
|
If your "program" needs to see the 3.5k characters, why are you displaying them to the user. Your ability to manipulate the data is not dependent on the UI. You UI should be collecting user input and displaying results.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Pablo Bozzolo wrote: The question here is WHY A more important question is: what problem are you actually trying to solve? The design of your application goes against most rules of development.
|
|
|
|
|
Hi,
WinForms (or any other GUI technology) wasn't designed to handle that many controls, you need a very different approach.
I suggest you look at my Sokoban article[^], which describes a board game of arbitrary size. It uses a single control (a Panel), that acts as a matrix of controls: it performs all drawing explicitly ("userdrawn"), and handles events collectively, i.e. most event handlers start with code to decide which cell of the board is being accessed. It isn't as easy as having a matrix of controls, but once you know how to identify the matrix cells, it becomes rather easy...
|
|
|
|
|
There are several things you could do to make your existing code run a bit faster, but I'm going to join the choir here singing that 3500 Labels are too much, and you need to change horses.
I think you will be surprised, as I was, how much you can do with making a grid by painting on a Panel; here's a screenshot from a 15x10 grid that I draw on a Panel: [^].
The "highlighted cell" you see is the result of a click on the Panel: that's a Label, sized to the cell-size in this example, that pops-up directly over the "cell" clicked; it presents information about the row,column address, and the cell id number.
The color scheme is generated algorithmically, stored in a data structure, and then mapped to the cells in the Paint EventHandler; this data is also computed in advance: the set of Rectangles of all cells in the grid; the set of strings painted into each cell. Of course, all brushes and pens are created outside the Paint EventHandler. The idea ... an obvious one ... is to get all possible computation, and whatever-creation, out of the Paint EventHandler.
Hit detection is very easy:
private void Grid1_MouseDown(object sender, MouseEventArgs e)
{
currentRow = e.Y/rowHeight;
currentColumn = e.X/columnWidth;
cellId = currentRow*columnCount + currentColumn;
PopLabel.Text = string.Format("{0},{1} {2}", currentRow, currentColumn, cellId);
PopUPPanel.Location = new Point(currentColumn*columnWidth, currentRow*rowHeight);
} I did try cranking up this prototype to 50 rows of 70 columns, and it drew very quickly (i7-4970k machine, Win 8.1, 8 gigs memory at present for testing purposes). But, I have no idea what to do with 3500 cells
«In art as in science there is no delight without the detail ... Let me repeat that unless these are thoroughly understood and remembered, all “general ideas” (so easily acquired, so profitably resold) must necessarily remain but worn passports allowing their bearers short cuts from one area of ignorance to another.» Vladimir Nabokov, commentary on translation of “Eugene Onegin.”
|
|
|
|
|
Good Morning
I have imported data into datagridView. The datagridView table has the following columns with the following meaning:
Date -Date when a particle was analysed.
Time -Time particle was analysed.
Analyzer - What analyzer was used to analyze the particle
Channel - What channel on the above mentioned analyzer was used
Sort - Is the classification of the particle, i.e "1" =concentrate; "0" = discard
H1 - H3- Measured values.
delay - how long the particle was measured for.
In excel I use sumifs or countifs functions to sort my data and calculate the weighted average H1 value for Analyzer 1. how do I go about and do this in c#
|
|
|
|
|
For a start, I wouldn't attempt to analyse the data based on it being in a DGV. If I were doing this, I would do all the work against a bindable collection and bind that to the DGV. To answer your question, you're going to have to write some mathematical analysis functions - no one's likely to just give you this here in a forum answer. If you Google, you should be able to find some suitable implementations that you could analyse.
This space for rent
|
|
|
|
|
You have to write the code yourself that does the calculation you want. You're probably setting the DataSource of your DataGridView to a DataTable, right? Use that DataTable also for your calculations. It's more convenient to handle than a DataGridView.
There are two options:
The traditional way: Loop over the rows in the DataRow-collection of the DataTable, read the values of the columns that are required for your calculation and then do the actual calculation. This would be a sample where I assumed double as the data type of your column "H1" and "some integer type" for the "Analyzer"-column:
double analyzer1Sum = 0;
int analyzerColumnIndex = myDataTable.IndexOf("Analyzer");
int h1ColumnIndex = myDataTable.IndexOf("H1");
foreach(DataRow row in myDataTable.Rows)
{
if(row[analyzerColumnIndex] == 1)
{
analyzer1Sum += row.Field<double>(h1ColumnIndex);
}
}
The LINQ way (assuming double as the data type of your column "H1" and int for the "Analyzer"-column):
int analyzerColumnIndex = myDataTable.IndexOf("Analyzer");
int h1ColumnIndex = myDataTable.IndexOf("H1");
double analyzer1Sum = myDataTable.AsEnumerable()
.Where(row => row.Field<int>(analyzerColumnIndex) == 1)
.Select(row => row.Field<double>(h1ColumnIndex))
.Sum();
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
modified 29-Feb-16 13:49pm.
|
|
|
|
|
Hi all,
Below is the code I have so far. It shows a column with image as its header but doesn't show the icon image.
Don't know enough yet about c# so any help will do.
dgvScore.Rows.Clear();
dgvScore.RowHeadersVisible = false;
dgvScore.ColumnCount = 2;
dgvScore.Columns[0].Name = "Name";
dgvScore.Columns[1].Name = "Score";
DataGridViewImageColumn img = new DataGridViewImageColumn();
img.Name = "img";
img.HeaderText = "Image";
img.ValuesAreIcons = true;
Image image = (Bitmap)Properties.Resources.ResourceManager.GetObject("diceicon.ico");
img.Image = image;
dgvScore.Columns.Add(img);
|
|
|
|
|
Your code is doing something completely different from what you're describing. You say you're trying to add an image to the header of the column, but what your code is doing is creating an ImageColumn which is a column in the DGV that displays images for every row.
So, which is it?
You have to custom draw the header row yourself if you're going to put an image in the header. For example, see this[^].
|
|
|
|
|
Hi Dave, thanks for looking, I am just trying to understand DataGridView. So a column with icons on every row is what I am after.
Having said that, I'll go and check out the link you have provided as well.
============================================================================
Edit:
Here's how I got it to work.
DataGridViewImageColumn img = new DataGridViewImageColumn();
img.Name = "img";
img.HeaderText = "Dice";
img.ValuesAreIcons = true;
dgvScore.Columns.Add(img);
Icon image0 = Properties.Resources.diceSix;
dgvScore.Rows[0].Cells["img"].Value = image0;
Icon image1 = Properties.Resources.diceOne;
dgvScore.Rows[1].Cells["img"].Value = image1;
modified 29-Feb-16 2:03am.
|
|
|
|
|
The documentation is really poor with the Rx functions:
Observable.Join(TLeft, TRight, TLeftDuration, TRightDuration, TResult) Method (System.Reactive.Linq)[^]
Got a little bit better by reading Lee's online book[^] and seeing the comments below this[^] Channel 9 video. So I finally managed to get something working (it is just a timer that tells for how long the left mouse button was pushed down):
var MouseDown = Observable.FromEventPattern<MouseButtonEventArgs>(this, "MouseDown");
var MouseUp = Observable.FromEventPattern<MouseButtonEventArgs>(this, "MouseUp");
var LeftMouseButtonPressedDuration = Observable.Join(
MouseDown
.Where(evt => evt.EventArgs.ChangedButton == MouseButton.Left)
.Select(_ =>
{
DateTime now = DateTime.Now;
return now;
}
),
MouseUp
.Where(evt => evt.EventArgs.ChangedButton == MouseButton.Left)
.Select(_ =>
{
DateTime now = DateTime.Now;
return now;
}
),
MouseDownTimeStamp => MouseDown,
MouseUpTimeStamp => Observable.Empty<DateTime>(),
(TimeDown, TimeUp) =>
{
TimeSpan MousePressedDuration = TimeUp - TimeDown;
return " Total duartion is: " + MousePressedDuration.ToString(@"ss\:fff");
}
);
LeftMouseButtonPressedDuration.Subscribe(evt =>
{
txtMainWindow.Text += Environment.NewLine + evt.ToString();
});
The two first sections are really easy to grasp, as well as the last function. But it is the third and fourth function inside Join that I really don't understand or even fully comprehend how to use. I assumed that it had something to do with how the events were interpreted. I assume that the 4th section,
MouseUpTimeStamp => Observable.Empty<DateTime>()
, is telling the compiler that when a new mouse down event happens, the mouse up will be cleared. If I changed the code slightly and put Publish() behind it:
MouseDownTimeStamp => MouseDown.Publish(),
MouseUpTimeStamp => Observable.Empty<DateTime>(),
It stored all the times since the first mouse down was pressed. Like a cross contry ski race where everyone starts at the same time, but arrive at the goal at different times.
So I tried to re-create the code that Lee had in his online book:
var Interval_50ms = Observable.Interval(TimeSpan.FromMilliseconds(50))
.Take(10);
var Interval_100ms = Observable.Interval(TimeSpan.FromMilliseconds(100))
.Take(5)
.Select(i => Convert.ToChar(i + 65).ToString().ToUpper());
var tt = Observable.Join(
Interval_50ms,
Interval_100ms,
s => Interval_50ms,
c => Observable.Empty<char>(),
(s, c) => { return s.ToString() + ", " + c.ToString(); })
.Subscribe(Console.WriteLine);
The output was just plain bizzare, at least to me:
3, A
3, A
3, B
6, D
8, E
I expected something like:
0, A
2, B
4, D
6, E
or at least an interval 2 between each char. What Am I doing wrong and/or what have I not understood here?
|
|
|
|
|
After some testing I seem to have found my answer:
var Interval_50ms = Observable.Interval(TimeSpan.FromMilliseconds(50))
.Take(10);
var Interval_100ms = Observable.Interval(TimeSpan.FromMilliseconds(100))
.Take(5)
.Select(i => Convert.ToChar(i + 65).ToString().ToUpper());
var Result = Observable.Join(
Interval_50ms,
Interval_100ms,
s => Observable.Never<Unit>(),
c => Observable.Empty<Unit>(),
(s, c) => { return s.ToString() + ", " + c.ToString(); })
.Subscribe(Console.WriteLine);
The two streams seems to start arbitrary, I cant seem to get the lined up properly, as it sometimes it will start at 0, A and other times 1, A . I think that the stream that is an s => Observable.Never<Unit>() just tells the compiler to store all the values that has come as a number into an Observable<T> , and by setting the c => Observable.Empty<Unit> it will basically publish all values it has stored in s and combine these with the new single value that it found at c .
This was also a point that confused me, that the s and c will return singular value at the time, but can be of the stream type of Observable<T> . So when I get the result in (s, c) => ... they are of type <T> .
By using the type Observable.Empty<Unit> if told it to just get me the next new value. The code seem to say: once you get a new char into c, print all the values in s with the value c.
Trying to understand how to create the latest value of s with the next value of c was however a bit tricky:
Observable.Join(
Interval_50ms,
Interval_100ms,
s => Interval_50ms,
c => Observable.Empty<char>(),
(s, c) => { return s.ToString() + ", " + c.ToString(); })
.Subscribe(Console.WriteLine);
This seem to produce some code that had some racing conditioning to it, so the results were a bit unstable.
|
|
|
|
|
I've seen you take quite some interest in Rx.
My 0.02$ - a lot of people (me included) would benefit from your research - why not write an article about it?
Best,
John
-- Log Wizard - a Log Viewer that is easy and fun to use!
|
|
|
|
|
The problem I have is that it takes me forever to figure out stuff, as the documentation is pretty poor sometimes. The problem here is that I still have some questions about Observable.Join, so I feel that I can't write it yet.
|
|
|
|
|
I completely understand. That's one of the reasons that kept me from learning Rx a while ago.
Best,
John
-- Log Wizard - a Log Viewer that is easy and fun to use!
|
|
|
|
|
|
Awesome, will read in a bit!
Best,
John
-- Log Wizard - a Log Viewer that is easy and fun to use!
|
|
|
|
|