ASP.NET add multiple series to chart via treeview selection - asp.net

My page has a chart that is set up to display data that is coming from a SqlDataSource.
There is a TreeView which contains a list of datapoints that I want to be able to add to the chart as different series. The user selects which item they wish to add by clicking a checkbox in the treeview for that node and then clicks an update button to refresh the chart.
Each node's value is set to a column name in the table.
If there is only one point selected on the treeview the data comes across as a series on the chart with no problem when the update button is clicked.
If multiple items in the treeview are selected an ASP.NET error page appears when clicking the button stating that a column name 'XXXX' was not found where 'XXXX' is the node.Value of the highest item in the tree that was checked.
For example an error saying that "Column with name 'X1' was not found" would show up when using the following selection:
If just 'X1' is checked the data shows up on the chart.
public void UpdateChart(Object sender, EventArgs e)
{
if (TagTreeView.CheckedNodes.Count > 0)
{
foreach (TreeNode node in TagTreeView.CheckedNodes)
{
// Add a series to the chart
Series series = new Series();
series=Chart1.Series.Add("Series"+node.Value);
series.ChartArea = "ChartArea1";
series.ChartType = (SeriesChartType)Enum.Parse(typeof(SeriesChartType), charts[1], true);
// create a datasource, add it to the page,
SqlDataSource sqlDataSource = new SqlDataSource();
sqlDataSource.ID = "SQLDataSource"+node.Value;
sqlDataSource.ConnectionString = ConfigurationManager.ConnectionStrings["HistoricalDataConnectionString"].ConnectionString;
if (node.Depth > 1)
{
if (node.Parent.Text.Contains("AAA"))
{
MessageBox.Show(node.Value);
sqlDataSource.SelectCommand = "SELECT (Date + CONVERT(datetime,Time)) As TimeStamp, " + node.Value + " FROM AAA ORDER BY TimeStamp";
}
this.Page.Controls.Add(sqlDataSource);
Chart1.DataSourceID = "SQLDataSource"+node.Value;
Chart1.Series["Series" + node.Value].XValueMember = "TimeStamp";
Chart1.Series["Series" + node.Value].YValueMembers = node.Value;
Chart1.DataBind();
}
}
}
}
Is there a way to take each selected item in the TreeView and use the node.value to build a query to add an additional series to the chart? I have done a little bit of work to see if putting the SqlDatasource and Series objects into an array and looping through that but it doesn't seem to be taking me anywhere.

To get this to work correctly all of the datapoints that will be added to the chart need to be included in the select statement for the sqlDataSource:
sqlDataSource.SelectCommand = "SELECT (Date + CONVERT(datetime,Time)) As TimeStamp, X1, X2, X3 FROM AAA ORDER BY TimeStamp";

Related

X++ assign Enum Value to a table column

I am trying to pull the Enum chosen from a dialog and assign the label to a table's column.
For example: Dialog opens and allows you to choose from:
Surface
OutOfSpec
Other
These are 0,1,2 respectively.
The user chooses OutOfSpec (the label for this is Out Of Spec), I want to put this enum's Name, or the label, into a table. The column I'm inserting into is set to be a str.
Here's the code I've tried, without success:
SysDictEnum dictEnum = new SysDictEnum(enumNum(SDILF_ScrapReasons));
reason = dialog.addField(enumStr(SDILF_ScrapReasons),"Scrap Reason");
dialog.run();
if (!dialog.closedOk())
{
info(reason.value());
return;
}
ttsBegin;
// For now, this will strip off the order ID from the summary fields.
// No longer removing the Order ID
batchAttr = PdsBatchAttributes::find(itemId, invDim.inventBatchId, "OrderId");
orders = SDILF_BreakdownOrders::find(batchAttr.PdsBatchAttribValue, true);
if (orders)
{
orders.BoxProduced -= 1;
orders.update();
}
// Adding a batch attribute that will include the reason for scrapping
select forUpdate batchAttr;
batchAttr.PdsBatchAttribId = "ScrapReason";
//batchAttr.PdsBatchAttribValue = any2str(dictEnum.index2Value(reason.value()));
batchAttr.PdsBatchAttribValue = enum2str(reason.value());
batchAttr.InventBatchId = invDim.inventBatchId;
batchAttr.ItemId = itemId;
batchAttr.insert();
Obviously this is not the whole code, but it should be enough to give the issue that I'm trying to solve.
I'm sure there is a way to get the int value and use that to assign the label, I've just not been able to figure it out yet.
EDIT
To add some more information about what I am trying to accomplish. We make our finished goods, sometimes they are out of spec or damaged when this happens we then have to scrap that finished good. When we do this we want to keep track of why it is being scrapped, but we don't want just a bunch of random reasons. I used an enum to limit the reasons. When the operator clicks the button to scrap something they will get a dialog screen pop-up that allows them to select a reason for scrapping. The code will then, eventually, put that assigned reason on that finished items batch attributes so that we can track it later in a report and have a list of all the finished goods that were scrapped and why they were scrapped.
I'm not entirely sure of your question, but I think you're just missing one of the index2[...] calls or you're not getting the return value from your dialog correctly. Just create the below as a new job, run it, make a selection of Open Order and click ok.
I don't know the difference between index2Label and index2Name.
static void Job67(Args _args)
{
Dialog dialog = new dialog();
SysDictEnum dictEnum = new SysDictEnum(enumNum(SalesStatus));
DialogField reason;
SalesStatus salesStatusUserSelection;
str label, name, symbol;
int value;
reason = dialog.addField(enumStr(SalesStatus), "SalesStatus");
dialog.run();
if (dialog.closedOk())
{
salesStatusUserSelection = reason.value();
// Label
label = dictEnum.index2Label(salesStatusUserSelection);
// Name
name = dictEnum.index2Name(salesStatusUserSelection);
// Symbol
symbol = dictEnum.index2Symbol(salesStatusUserSelection);
// Value
value = dictEnum.index2Value(salesStatusUserSelection);
info(strFmt("Label: %1; Name: %2; Symbol: %3; Value: %4", label, name, symbol, value));
}
}

Very simple if else check in Google App Maker

This is likely embarrassingly easy but I'm new and I've been beating my head against the wall on this for a while now. What I am attempting to do is basically a modified version of the "Hello App Maker!" If else test.
The necessary info I have the following widgets attached to the appropriate data sources:
Dropdown widget called source_name (string - list)
Label widget I've called name (string)
Text Box widget called qty_duration (number)
Label widget I've called hours (number)
I have a dropdown widget called source_name with 5 options. On selection I have the value appear in a label widget I've called name. If the option selected from the drop down widget is ever LABOUR I am trying to then have the value of a Text Box widget called qty_duration appear in a label widget I've called hours
On the source_name dropdown event - onValueChange I have the following code:
// Define variables for the input and output widgets
var nameWidget = app.pages.Apex_job_details.descendants.name;
var outputWidget = app.pages.Apex_job_details.descendants.hours;
var techhours = app.pages.Apex_job_details.descendants.qty_duration;
var nothing = 0;
// If a name is LABOUR, add the qty to the output widget Else output 0.
if (nameWidget == 'LABOUR') {
outputWidget.text = techhours;
} else {
outputWidget = nothing;
}
It's not giving me any errors, but it's also not outputting to the hours label. If I edit the code as follows just to muck with it:
// Define variables for the input and output widgets
var nameWidget = app.pages.Apex_job_details.descendants.name;
var outputWidget = app.pages.Apex_job_details.descendants.hours;
var techhours = app.pages.Apex_job_details.descendants.qty_duration;
var nothing = 0;
// If a name is LABOUR, add the qty to the output widget Else output 0.
if (nameWidget == 'LABOUR') {
outputWidget.text = techhours;
} else {
outputWidget.text = nothing;
}
I'm not sure what I'm doing wrong.
Assuming all labels and input widgets are inside a table row you will want to adjust your code as follows:
var tablerow = widget.parent;
var nameWidget = tablerow.descendants.name.text;
var outputWidget = tablerow.descendants.hours;
var techhours = tablerow.descendants.qty_duration.value;
if(nameWidget === 'LABOUR') {
outputWidget.text = techhours;
} else {
outputWidget.text = null;
}
By using widget.parent in the onValueChange event of the dropdown you will automatically reference the table row and then by using descendants you are referencing only the descendants of that table row. This will bridge the error by using an absolute reference when using table rows. If it still doesn't work let me know.

D365 New Button creates price line with empty line

After adding logic about creating price for object in grid it's always created "one line more" which is empty.
So, if there is need to be created two lines, it will be created 3 lines and that one addition will be empty.
Is there something what I missing in code?
[Control("CommandButton")]
class AreaActionPaneNew
{
void clicked()
{
PMCParameters contractParameters = PMCParameters::find();
PMETmpRentalObjectArea groupedAreaList; // Group by area_type and cost_type
PMERentalObjectPrice priceList;
date workingDate = currWorkingDate.dateValue();
;
super();
// Get grouped area values. Values are summed up by area_type and ancost_type
groupedAreaList = PMERentalObjectAreaCl::getRentalAreaPrCostType(pmeRentalobject.RentalObjectId, userSetting.validFrom(), userSetting.validTo() , workingDate);
ttsbegin;
while select groupedAreaList
{
select forupdate firstonly priceList
where priceList.RentalObjectId == pmeRentalObject.RentalObjectId &&
priceList.RentalCostType == groupedAreaList.RentalCostTypeId &&
priceList.AreaType == groupedAreaList.Areatype && priceList.ValidFrom == pmeRentalObject.ValidFrom;
if (!priceList)
priceList.initValue();
priceList.RentalObjectId = pmeRentalObject.RentalObjectId;
priceList.RentalCostType = groupedAreaList.RentalCostTypeId;
priceList.ValidFrom = pmeRentalobject.ValidFrom;
priceList.AreaType = groupedAreaList.Areatype;
priceList.Amount = groupedAreaList.Price;
priceList.Area = groupedAreaList.AreaValue;
priceList.Quantity = groupedAreaList.RentalQty;
if (!priceList)
priceList.Period = contractParameters.ReportPeriod;
if (priceList)
priceList.update();
else
priceList.insert();
}
ttscommit;
pmeRentalObjectPrice_ds.research();
}
}
The code looks like it only updates/inserts without creating a blank line.
From your attribute, you are using a Command Button (see here), which may have an associated command, such as New, which effectively pushes Ctrl+N, and would explain why you have a blank line.
The simplest way to check is just create a regular Button and override the clicked method, then copy/paste your code and push both buttons and see if they have different behavior.
Check the Command property on the button and see if there's something there. Try commenting out the super(); call.
You should perhaps consider just a Button or a Menu Item Button with an associated object.

AppMaker - Navigate to Last Page on Table

Scenario:
I have a calculated SQL that returns 100 results.
Added a table (from this calculated SQL) and limited the size of the page by 25 results.
This will generate 4 pages.
Pager form AppMaker works well (navigates between pages) but i need a button that navigates directly from page 1 to the page 4.
is this possible?
Anyone got a solution for this?
Regards
If you need to know how many entries your table has (in your case it's seems fixed to 100, but maybe it could grow), you can still do what you want:
E.g. say your table on YOURPAGE depends on a datasource called Customers.
Create a new Data item called CustomerCount, with just one field, called Count (integer).
Its data source would be a sql query script:
Select count(CustomerName) as Count from Customers
on the page you are having the table on, add a custom property (say called
Count of type integer)
In the page attach event, set the property asynchronously with this custom action:
app.datasources.CustomerCount.load(function() {
app.pages.YOURPAGE.properties.Count = app.datasources.CustomerCount.count;
app.datasources.Customers.query.pageIndex = #properties.Count / 25;
app.datasources.Customers.datasource.load();
});
I tried similar things successfully in the past.
Found a solution for this:
ServerScript:
function CandidateCountRows() {
var query = app.models.candidate.newQuery();
var records = query.run();
console.log("Number of records: " + records.length);
return records.length;
}
in the button code:
var psize = widget.datasource.query.pageSize;
var pidx = widget.datasource.query.pageIndex;
var posicao = psize * pidx;
var nreg = posicao;
google.script.run.withSuccessHandler(function(Xresult) {
nreg = Xresult;
console.log('position: ' + posicao);
console.log('nreg: ' + nreg);
console.log('psize: ' + psize);
console.log('pidx: ' + pidx);
var i;
for (i = pidx; i < (nreg/psize); i++) {
widget.datasource.nextPage();
}
widget.datasource.selectIndex(1);
}).CandidateCountRows();
This will allow to navigate to last page.
If you know for a fact that your query always returns 100 records and that your page size will always be 25 records then the simplest approach is to make sure your button is tied to the same datasource and attach the following onClick event:
widget.datasource.query.pageIndex = 4;
widget.datasource.load();

Multiple ASP.NET DropDownLists are being set to the same value

I have 6 dropdown lists (with identical options), and I am manually setting them in my codebehind. All six should have different values. When I log the values I am setting them to, I get the correct assumed values to be set to. However, when the page renders, all six of them are set to the same freaking value.
I have tried setting the values with all of the following:
// set index, find by text
dd1.SelectedIndex = dd1.Items.IndexOf(dd1.Items.FindByText(val1));
// set with selected value
dd2.SelectedValue = val2;
// set index, find by value
dd3.SelectedIndex = dd3.Items.IndexOf(dd3.Items.FindByValue(val3));
// set list item, selected = true
((ListItem)dd4.Items.FindByValue(val4)).Selected = true;
The dropdown lists' set of options are generated prior to me trying to set them:
foreach (Station st in stations) {
ListItem li = new ListItem() { Text = st.fromto, Value = st.fromto};
dd1.Items.Add(li);
dd2.Items.Add(li);
dd3.Items.Add(li);
dd4.Items.Add(li);
dd5.Items.Add(li);
dd6.Items.Add(li);
}
I then look in the database to see if any values exist for a specific reference id in my app. If so, it indicates that I need to set one or more (up to 6) dropdowns:
var existingStations = db.LOGOPS_STATIONs.Where(x => x.XREF_LOGOP_MAIN_ID == logopRefId);
if (existingStations.Count() > 0) {
int i = 1;
foreach (LOGOPS_STATION s in existingStations) {
if (i < 7) {
string text= s.FROM_STATION;
if (i == 1) dd1.SelectedIndex = dd1.Items.IndexOf(dd1.Items.FindByText(text));
// for the heck of it, set the next one manually...
else if (i == 2) dd2.SelectedIndex = 2;
// try and set one with forcing select
else if (i == 3) ((ListItem)dd3.Items.FindByText(text)).Selected = true;
// good ol normal
else if (i == 4) dd4.SelectedValue = text;
... and so on ...
}
}
}
So, the dropdowns are all populated (when I log in the codebehind they're fully populated). And when I log the actual values when they're being set, they're set to the value as expected. However, when the page loads, they're all set to the same thing
At any rate, not sure what else to do. I have turned on and off different event validation hookups. I have disabled all JS to see if that was manipulating values, and it's not. I have tried explicitly setting like this
dd1.SelectedIndex = 2;
dd2.SelectedIndex = 8;
Oddly enough, that doesn't work either. For real, when does setting SelectedIndex to a unique control with a unique id not set the item?
I had to create a separate list item for each dropdown instead of them all sharing the same li in the foreach loop. And then a step further, had to set Selected = false in the constructor of the ListItem
I assumed that you could 'reuse' code for each instance of the dropdown population, but each dropdown needed it's own unique ListItem
Maybe there's a better way, but this solution seems to have solved the problem

Resources