I am reading data from Firebase Firestore and displaying it using a Cartesian Chart. Here is the function that takes some data parameters and then draws the graph:
public void DrawGraph(double allowed, double denied, double pending)
{
cartesianChart1.Series = new SeriesCollection
{
new ColumnSeries
{
Title = DateTime.Today.ToString("dd/MM/yyy"),
Values = new ChartValues<double> { allowed, denied, pending },
}
};
cartesianChart1.AxisX.Add(new Axis
{
Title = "Requests",
Labels = new[] { "Allowed", "Denied", "Pending"}
});
}
Here is the actual output:
The problem here is that the labels "Allowed", "Denied", and "Pending" are not appearing as they should, e.g.
In this case, the data isn't loaded and the graph code is written inside the constructor of the parent WinForm. And when the data is loaded it shows the same results as shown in the first image.
Related
How can I create an inline keyboard with several buttons, one per row?
like:
inlineBtn1
inlineBtn2
inlineBtn3
...
not:
inlineBtn1 inlineBtn2 inlineBtn3 ...
I Solved it
await bot.SendTextMessageAsync(e.Message.Chat.Id, "test", replyMarkup: new InlineKeyboardMarkup(
new InlineKeyboardButton[][]
{
new [] { new InlineKeyboardButton() { Text = "btn 1",CallbackData="Some data1" } }, // buttons in row 1
new [] { new InlineKeyboardButton() { Text = "btn 2", CallbackData = "Some data2" } }, // buttons in row 2
new [] { new InlineKeyboardButton() {Text = "btn 3", CallbackData = "Some data3" } }// buttons in row 3
}));
We must use exactly one of the optional fields.
So you have to pass either url, callback_data or switch_inline_query The button would be useless if you don't pass any of those fields.
To send a message to a chat with an inline keyboard use the replyMarkup parameter of TelegramBot.SendMessage or TelegramBot.SendMessageAsync method. It can be either ReplyKeyboardMarkup or InlineKeyboardMarkup. A constructor of InlineKeyboardMarkup accepts an array of button rows (each of them, in turn, comprises an array of buttons in the given row). To create an inline keyboard with several buttons one per row pass an array with several rows with one element each:
TelegramBot bot = ...;
Chat chat = ...;
await bot.SendMessageAsync(chat.Id, "A message. Use the keyboard below.",
replyMarkup: new InlineKeyboardMarkup(
new InlineKeyboardButton[][]
{
new [] { new InlineKeyboardButton("inlineBtn1") }, // buttons in row 1
new [] { new InlineKeyboardButton("inlineBtn2") }, // buttons in row 2
new [] { new InlineKeyboardButton("inlineBtn3") } // buttons in row 3
}));
The message should look like this:
I've got a 'dashboard' with several charts on it. One of them is a pie chart with a number of series.
LiveCharts has a DataClick event
DataClick(object sender, ChartPoint chartPoint)
sender is of type PieSlice. How can i access SeriesCollection from that event or, alternatively, chart name / id?
What I am trying to achieve is access chart that sent the event, then it's series collection and check which of the series / pie slice fired the event.
First and foremost, don't use events, use commands - that's the MVVM way. i.e.
<LiveCharts:PieChart DataClickCommand="{Binding DrillDownCommand}" Series="{Binding MySeries}" ...>
Note the binding to MySeries:
public SeriesCollection MySeries
{
get
{
var seriesCollection = new SeriesCollection(mapper);
seriesCollection.Add(new PieSeries()
{
Title = "My display name",
Values = new ChartValues<YourObjectHere>(new[] { anInstanceOfYourObjectHere })
});
return seriesCollection;
}
}
And about handling the command:
public ICommand DrillDownCommand
{
get
{
return new RelayCommand<ChartPoint>(this.OnDrillDownCommand);
}
}
private void OnDrillDownCommand(ChartPoint chartPoint)
{
// access the chartPoint.Instance (Cast it to YourObjectHere and access its properties)
}
You need to work with arguments, not the sender. The second parameter is ChartPoint, that cointains SeriesView. So just access it and use it's Title:
private void Chart_OnDataClick(object sender, ChartPoint chartpoint) {
MessageBox.Show(chartpoint.SeriesView.Title);
}
How can i access SeriesCollection from that event or, alternatively, chart name / id?
SeriesView is not the whole SeriesCollection, but Series you clicked on. And you can have it's name
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;
}
I have a Xamarin forms application which has an event that runs every second and fetches data from a Characteristic. In this event I create the whole layout, set the data and update the view like this:
public void UpdateDisplay (ICharacteristic c) {
//Lots of irrelevant code above this.
foreach (Accelerometer item in acceloReadings)
{
counter += 1;
//Y-graph data
DataPoint itemPointY = new DataPoint();
itemPointY.X = counter;
itemPointY.Y = item.yAxes;
PointsY.Add(itemPointY);
}
yAs = new PlotModel("Variations Y-Axis");
yAs.PlotType = PlotType.XY;
yAs.Axes.Add(new LinearAxis(AxisPosition.Left, -270, 270));
y = new LineSeries();
//Custom color
y.Color = OxyColor.FromArgb(255, 154, 200, 253);
y.ItemsSource = PointsY;
yAs.Series.Add(y);
opvY = new OxyPlotView
{
WidthRequest = 100,
HeightRequest = 100,
BackgroundColor = Color.Aqua
};
opvY.Model = yAs;
Content = new StackLayout
{
opvY,
}
};
}
That code fills up all the models etc and I then want to update my graphs in the same method. I've tried a few ways:
//After all the data is re-loaded and added I want to refresh my graphs.
xAs.InvalidatePlot(true);
opvX.Model.InvalidatePlot(true);
opvX.InvalidateDisplay();
However none of these have any succes. When you look at the official docs you can see clearly it states:
"To update the plot, you must do one of the following alternatives:
Change the Model property of the PlotView control
Call Invalidate on the PlotView control
Call Invalidate on the PlotModel"
While I've tried all these ways none of them update my graphs/view. When I manually click and resize the graph I can see the data is refreshed. Eventually I want to create the graphs just once in the main method and then update the graphs with the InvalidateDisplay.
So, what am I doing wrong?!
So, I've got a list view, as indicated by the question title. I've got two columns set up: Name and Date Modified. These were added in the designer, here's the code emitted by the designer for reference:
// lstFiles
this.lstFiles.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.clmName,
this.clmDate});
// ...
// clmName
this.clmName.Text = "Name";
this.clmName.Width = 105;
// clmDate
this.clmDate.Text = "Modified";
this.clmDate.Width = 128;
In the designer, this looks beautiful.
The list items themselves are a tiny subclass of ListViewItem that simply extracts some metadata from a file (in this case, the date modified), and adds a sub-item to itself:
class GalleryItem : ListViewItem {
public string File;
public DateTime DateModified;
public GalleryItem(string file) : base(Path.GetFileNameWithoutExtension(file)) {
this.ImageKey = Path.GetExtension(file);
File = file;
DateModified = System.IO.File.GetLastWriteTime(file);
this.SubItems.Add(DateModified.ToString());
}
}
To add items to the list, I simply do this:
lstFiles.BeginUpdate();
lstFiles.Clear();
foreach (String f in files) {
ListViewItem lvi = new GalleryItem(f);
lvi.Group = lstFiles.Groups["grpFiles"]; //this varries
//omitted: check/add icon to list
lstFiles.Items.Add(lvi);
}
lstFiles.EndUpdate();
So, this all works great for Large Icon view, etc:
However, it breaks down on Details view:
There are items in the list (there's a scroll bar). If you click roughly in the column under the red arrow (added in paint), you'll select an item (the upper-right area is an image preview), but you won't see anything selected.
In summary, what am I doing wrong?
I just whipped up a sample to test this:
using System;
using System.Windows.Forms;
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var G1 = new ListViewGroup("Group 1");
var G2 = new ListViewGroup("Group 2");
Application.Run(new Form {
Controls = {
new ListView {
Dock = DockStyle.Fill,
Groups = { G1, G2 },
View = View.Details,
//Columns = { "First", "Second" },
Items = {
new ListViewItem { Text = "One", Group = G1, SubItems = { "1" } },
new ListViewItem { Text = "Two", Group = G2, SubItems = { "2" } },
new ListViewItem { Text = "Three", Group = G2, SubItems = { "3" } },
},
},
},
});
}
}
You will notice that it duplicates the problem. If you uncomment the line that creates the columns it works. This suggests that your columns don't exist.
And while typing this the answer popped into my head:
You are calling ListView.Clear instead of ListView.Items.Clear so you are removing the columns in code.
My understanding is that you are not able to use Groups in Details view. I can't test this right now, so I am going off straight memory. However, try populating your list without the Groups and see what happens. I strongly suspect it is the Group part that is causing the problem.
I had exactly the same problem identified by Tergiver, but there is one more gotcha - when you add the columns, the ListView must be in View.Details mode.