So I'm having a really weird problem in C# WindForm. I've tried to create a chart. In the area where the chart itself should exist, the problem is that it displays no data. It just looks like that:
That's my code:
int questionsAmount = setData.questionsAmount;
var dates = new List<DateTime>();
foreach(var item in setData.dates)
{
dates.Add(Convert.ToDateTime(item));
}
int[] records = setData["records"].ToObject<int[]>();
Series series = new Series("records");
series.Points.DataBindXY(dates, records);
series.ChartType = SeriesChartType.Spline;
chart = new Chart();
chart.Name = set.title;
chart.Series.Add(series);
chart.Series["records"].SetDefault(true);
chart.Series["records"].Enabled = true;
chart.BackColor = SystemColors.Highlight;
Controls.Add(chart);
Refresh();
Any help would be much appreciated. Thanks!
Hmm.. First, because we cannot read the entire code, I cannot sure the data generating process is working well. As your picture, the chart control is added. Maybe you can add breakpoint on "series.Points.DataBindXY(dates, records);" and check whether the data is ready or not.
FYI, another probable issue is you need to do UI operation in main thread (UI thread) if you didn't.
Hope these can help you.
Related
I have been looking for solution for days now and still have done nothing.
I have an database which, as one of the values has URL for picture, let´s say the attribute name is Picture_Link, I can show URL in data grid view but I have to show it as a picture with all other columns and rows.
In other data grid I have to show pictures directly from link that I have from app-i result.
All objects in data grid are shown via list which I import from data base (CRUD) and other one is via app-i key result.
CRUD Video = new CRUD();
List<YouTubeVideo> list = Video.GetVideosDB();
dataGridYT.DataSource = list;
This is how my view is imported.
Also I have some added columns, such as save and delete which are type image.
DataGridViewImageColumn oSaveButton = new DataGridViewImageColumn();
oSaveButton.Image = Image.FromFile("D:/save.png");
oSaveButton.Width = 50;
oSaveButton.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dataGridYT.Columns.Add(oSaveButton);
dataGridYT.AutoGenerateColumns = false;
And CellContntClick functions which work.
Everything works except dinamic upload of images in both of data grid views.
private void dataGridYT_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (dataGridYT.Columns[e.ColumnIndex].Name == "Thumbnail")
{
e.Value = GetImageFromUrl("https://i.ytimg.com/vi/oZItXZtkmzg/default.jpg");
dataGridYT.Columns[e.ColumnIndex].DefaultCellStyle.BackColor = Color.Azure;
}
}
private object GetImageFromUrl(string url)
{
HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
using (HttpWebResponse httpWebReponse = (HttpWebResponse)httpWebRequest.GetResponse())
{
using (Stream stream = httpWebReponse.GetResponseStream())
{
return Image.FromStream(stream);
}
}
}
I have tried this.
Still nothing, tried to make new data grid with only one column, have copied working code from repos and that one won´t work either. But if I make whole new solution it works. Added new column also.
I have tab control, with two tabs. Each tab has one data grid view, one of the columns shows values of image url´s which I have to use to show a picture, also I need that link for saving whole row in db. I have tried with foreach loop to get each cell value with link and to add image with function in code above.
dataGridYT.CellFormatting +=
new System.Windows.Forms.DataGridViewCellFormattingEventHandler(
this.dataGridYT_CellFormatting);
This line was missing and it fixed problems from above. I goes just under the code where I have added image cells such as oSaveButton.
DataGridViewImageColumn oSaveButton = new DataGridViewImageColumn();
oSaveButton.Image = Image.FromFile("D:/YouTube_KV/save.png");
oSaveButton.Width = 50;
oSaveButton.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dataGridYT.Columns.Add(oSaveButton);
dataGridYT.AutoGenerateColumns = false;
dataGridYT.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
dataGridYT.Rows.Add(Environment.NewLine);
dataGridYT.CellFormatting +=
new System.Windows.Forms.DataGridViewCellFormattingEventHandler(
this.dataGridYT_CellFormatting);
dataGridYT.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
I am trying to use live chart for wpf c#. Generally I got it to work to display a graph. However when i try to call the function below more than once it does not execute the second time. Why? If I restart the program it works but only the first time again. Anybody familiar with live charts (lvcharts) library and can give me some direction. Thank you!
public void FillTheGraph(string[] axisX, double[] axisY)
{
SeriesCollection = new SeriesCollection
{
new LineSeries
{
Title = "Graph",
Values = new ChartValues<double>(axisY)
},
};
Labels = axisX;
DataContext = this;
}
If I have a candle series drawn on the teechart, and I change the last candle's CloseValue, the candle does not automatically update on the chart. I don't really want to invalidate the whole chart to show it because if there are a lot of candles, that's slow. I thought the DrawValue method of the Candle series would solve this, but it seems that it actually redraws the whole chart as well. Is there a way to update/redraw on screen just that one candle?
I know when I was doing this in Delphi 5 the candle seemed to update without redrawing the whole chart - although maybe the whole chart updates were fast enough that it just seemed that way. In general, it seems that C#'s Teechart draws are 3 to 5 times slower than the Delphi 5 VCL Teechart's draws...
I think you can use the method that allow refresh only the series, RefreshSeries, as do in next line of code:
candle1.RefreshSeries();
Could you tell me, if it works for you? If you have any problems please let me know.
Update information to answer next question:
Ok, I guess I am not explaining myself well here, Sandra. Let me try
again. Let's say I have a chart that has only one series - 30,000
candles. Let's say I show ALL candles on the chart. Redrawing all 30K
candles takes time. Let's say the code changes only ONE candle - the
last one. Is there any way to just repaint that little portion of the
chart that has the new candle, and not repaint the whole chart in
order to show the new change? I tried Invalidate function passing it
the candle's rectangle, but it seems that Invalidate() and
Invalidate(rect) produce exactly same results.
Can you tell us which version of TeeChart are you using?. In the other hand, I have made a simple code where I have modified the CloseValue and I have released that isn't necessary repaint, redraw or refresh Series because the value is updated automatically. I have made the test using last version of TeeChartFor.Net Build number [4.1.2012.01312] and next code:
Steema.TeeChart.Styles.Candle candleSeries1;
Random r;
double tmpOpen;
double tmpClose;
int count;
DateTime dt;
TimeSpan ts;
private void InitializeChart()
{
tChart1.Aspect.View3D=false;
tChart1.AutoRepaint = false;
r = new Random();
candleSeries1.Clear();
candleSeries1.XValues.DateTime = true;
candleSeries1.GetHorizAxis.Labels.Angle = 90;
count = 0;
dt = DateTime.Today;
ts = TimeSpan.FromDays(1);
candleSeries1.Pen.Visible = false;
for (int t=0;t<30000;t++)
{
tmpOpen = r.Next(100);
tmpClose = tmpOpen - r.Next(100);
++count;
candleSeries1.Add(dt,tmpOpen,tmpOpen + r.Next(50),
tmpClose -r.Next(50),tmpClose);
dt += ts;
}
tChart1.AutoRepaint = true;
}
private void button1_Click(object sender, EventArgs e)
{
tmpOpen = r.Next(100);
tmpClose = tmpOpen - r.Next(100);
candleSeries1[candleSeries1.LastVisibleIndex].Close = tmpOpen;
}
Thanks,
I have written below piece of code to change background color of table cell of ppt using c# code but nothing is happening:
//creating powerpoint aaplication
PowerPoint.Application pptApp = new PowerPoint.Application();
pptApp.Visible = Office.MsoTriState.msoTrue;
var pptPresent = pptApp.Presentations;
var fileOpen = pptPresent.Open(#file, Office.MsoTriState.msoFalse, Office.MsoTriState.msoTrue, Office.MsoTriState.msoTrue);
// getting first slide
PowerPoint.Slide objSlide = fileOpen.Slides[1];
PowerPoint.Shapes item = objSlide.Shapes;
// getting first shape
var shape1 = item[1];
// check if shape is table
if (shape1.HasTable == Office.MsoTriState.msoTrue)
{
// change the table cell to red color
shape1.Table.Cell(2, 5).Shape.Fill.BackColor.RGB = System.Drawing.Color.Red.ToArgb();
// make it visible
shape1.Fill.Visible = Office.MsoTriState.msoTrue;
}
// saving the ppt
fileOpen.SaveAs(openFolder + subStr + ".pptx",PowerPoint.PpSaveAsFileType.ppSaveAsDefault,Office.MsoTriState.msoTrue);
// close the ppt
fileOpen.Close();
Above piece of code is not working as expected, can someone help me?
To change the cell color ForeColor needs to be used instead of BackColor. Drawing colors may not work as expected. To change that use ColorTranslator.
shape1.Table.Cell(2, 5).Shape.Fill.ForeColor.RGB = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red);
Great question! The Fill property is also available for the Shape object, wether it's a Cell or a another type of Shape.
Another example for the Fill property is mentioned in this thread:
https://stackoverflow.com/a/26253177/20337158.
Also from the Microsoft learning sites:
https://learn.microsoft.com/en-us/previous-versions/office/office-12/ff763049(v=office.12)
I'm trying to implement datagridview's virtual mode but when i set RowCount to some number (to show the scrollbar) the grid wants to have all rows at once, not only the displayed.
DataGridView grid = new ...;
grid.VirtualMode = true;
grid.CellValueNeeded += OnCellValueNeeded;
grid.RowCount = dataprovider.GetFullCount();
How can i tell the grid to only request the rows displayed?
This is just a guess, but do you have the AutoSizeRowsMode or AutoSizeColumnsMode values set to AllCells or are any of the columns set to that either? Try setting the resize mode to None or just DisplayedCells and see if there is still a problem.
Not sure if this is the same problem as I was having, but I did get very poor performance when regularly drastically changing the RowCount on a VirtualMode DataGridView.
What I noticed was that the scroll bar was changing "slowly"; i.e. it looked like it was individually removing my virtual rows (!).
Anyway, doing a grid.Rows.Clear() before each call to grid.RowCount = n drastically improved performance.
You should set the RowCount to zero before setting the full count.
DataGridView grid = new ...;
grid.VirtualMode = true;
grid.CellValueNeeded += OnCellValueNeeded;
grid.RowCount = 0;
grid.RowCount = dataprovider.GetFullCount();
unfortunatly this seems to be the standard behavior. i could solve it either by
void OnCellValueNeeded(...)
{
if(!_active) return;
}
grid.VirtualMode = true;
grid.CellValueNeeded += OnCellValueNeeded;
_active = false;
grid.RowCount = dataprovider.GetFullCount();
_active = true;
or implementing IBindingList, ITypedList with complex lazy fetching in background thread
Update: the problem seems to be fixed now. I can not reproduce it anymore using the following:
static class Program
{
private static Form form;
private static int i;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var grid = new DataGridView
{
Dock = DockStyle.Fill,
VirtualMode = true,
AllowUserToAddRows = false,
Columns =
{
new DataGridViewTextBoxColumn { HeaderText = "foo" },
new DataGridViewTextBoxColumn { HeaderText = "bar" },
},
};
grid.CellValueNeeded += OnCellValueNeeded;
form = new Form
{
Controls = { grid }
};
//grid.RowCount = 0;
grid.RowCount = 10000;
Application.Run(form);
}
private static void OnCellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
i++;
form.Text = i.ToString();
e.Value = "fooValue";
}
}
I'm having the same issue and I tried the solution of setting an active flag like you did, and I also tried the solution of setting the RowCount to 0 (or grid.Rows.Clear()) before setting the new RowCount.
Both of these things improved performance, but neither sped it enough to be as instantaneous as I want because I am dynamically filtering the grid in real time based on input from a search box.
I found two other solutions:
1) Use pagination so that you don't have to set the RowCount so high to begin with. I think this is a great solution if you are already using pagination (in which case you wouldn't be here) but an overly cumbersome one if you weren't planning on implementing it.
2) Put the call to set the RowCount in its own thread. This is the one I'm about to attempt. Honestly not sure how safe this one is if you're trying to edit cells while the thread is still finishing up but I guess I'll find out soon enough.
EDIT:
OK, so I tried threading it hoping that would do the trick since I read elsewhere that it really helped another guy. It seems to be a good solution IF you are just going to change the value once in a while but it still hangs if you do it multiple times consecutively (which I am). I think this is because you have to use Invoke() and the second time around it's still waiting for the first one to finish. Can't say I totally understand what the deal is but I've decided just to live with the blank rows for now because it's SOOO much faster and less complex when I just leave them there.