How do I select an element from CollectionView without using the click on an element - collectionview

I want to make a habits tracker app and I used the CollectionView and I stood at the StreakCount I want when I click on CheckBox add to the database and to the Label a number and this number is Streak but I face a problem in defining the habit, meaning how can I specify the habit that I want to add to it the streak without Select the item by clicking on it from CollectionView,
I tried IValueConverter and some Functions but couldn't without specifying which habits I want to change
** <Label Text="{Binding Source={x:Reference StreakCheckBox}, Path=IsChecked,
Converter= {x:StaticResource converter01}}"
FontSize="15" TextColor="LightGreen"
VerticalOptions="End" Margin="-3,0,0,0" />**
** <CheckBox HorizontalOptions="EndAndExpand"
x:Name="StreakCheckBox"/>**
** Habits habit = new Habits();
public object Convert(object value, Type targetType, object parameter, CultureInfo
culture)
{
if (value == null)
return null;
bool result = (bool)value;
if (result)
{
int result02 = int.Parse(habit.StreakCount) + 1;
return habit.StreakCount = result02.ToString();
}
else
{
int result02 = 0;
return habit.StreakCount = result02.ToString();
}
} **
Image

Related

FGetting a Form Field from a grid extension

I have added a field to the Prepare Replenishment form that needs to be updated when a user selects a row in the Replenishment Item grid. How do I access the field. I know it is in the INReplenishmentFilterExt but I can't figure out how to get access to the extension.
Edit #1: I am able to get the value of the field but it does not update on the screen when I use cache.SetValue. I am trying to update this filter extension field from inside of the Selected event handler.
protected void INReplenishmentItem_Selected_FieldUpdating(PXCache cache, PXFieldUpdatingEventArgs e)
{
var row = (INReplenishmentItem)e.Row;
if (row == null)
return;
INReplenishmentFilter filter = Base.Filter.Current;
INReplenishmentFilterExt filterExt = PXCache<INReplenishmentFilter>.GetExtension<INReplenishmentFilterExt>(filter);
decimal poAmount = filterExt.UsrPOAmount.HasValue ? filterExt.UsrPOAmount.Value : 0;
decimal lastPrice = pvi.LastPrice.HasValue ? pvi.LastPrice.Value : 0;
decimal newPOAmount = poAmount + lastPrice;
cache.SetValue<INReplenishmentFilterExt.usrPOAmount>(filterExt, newPOAmount);
}
You cannot set the value of the Filter using the Cache of INReplenishmentItem.
I have edited my answer, the code below should work.
//Always use virtual methods for Event Handlers
protected virtual void INReplenishmentItem_Selected_FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
//Try not to use vars. Especially when you know the Type of the object
INReplenishmentItem row = e.Row as INReplenishmentItem;
if (row != null)
{
INReplenishmentFilter filter = Base.Filter.Current;
INReplenishmentFilterExt filterExt = PXCache<INReplenishmentFilter>.GetExtension<INReplenishmentFilterExt>(filter);
decimal poAmount = filterExt.UsrPOAmount ?? 0;
decimal lastPrice = pvi.LastPrice ?? 0;//Not sure what pvi is
decimal newPOAmount = poAmount + lastPrice;
//"sender" is the cache that specifically stores the datatype of row
//Therefor you cannot use it to update records of a different datatype
//You also should not pass an Extension into the argument that should be the row object you are trying to update
Base.Filter.Cache.SetValueExt<INReplenishmentFilterExt.usrPOAmount>(filter, newPOAmount);
}
}

Popup exceptions in line items (SOLine)

How to display popup exceptions instead of the one with a red dot on the row for the line items? I was able to have them in RowInserting for a little bit but after a series of code changes I get the red dot one instead. It even did not create a new row as I wanted but now it does. RowInserting event:
protected virtual void SOLine_RowInserting(PXCache sender, PXRowInsertingEventArgs e)
{
var listMissingOEdesc = new List<int>();
var select = Base.Transactions.Select();
foreach (SOLine row in select)
{
var isOEDesc = IsOEDescEnabled(sender, row);
var rowExt = PXCache<SOLine>.GetExtension<SOLineExt>(row);
if (isOEDesc == true)
if (rowExt.UsrOedesc == null)
listMissingOEdesc.Add(row.SortOrder.Value);
}
if (listMissingOEdesc.Count > 0)
{
throw new PXException("Line items with sort order {0} do not have OE Desc filled out. Cannot add a new line.", string.Join(", ", listMissingOEdesc));
}
else
Base.Actions.PressSave();
}
Thanks!
There is no easy way, if any at all, to display popup exception and prevent the grid from inserting a new row. The way the framework is designed, PXGrid first inserts a new row on the webpage. After that PXGrid sends a callback to the application server either requesting default field values for the new row (if PXGrid's Mode has InitNewRow="True") or sends all values captured from the webpage to the application server, so the new row can be inserted in the PXCache. Whenever an event handler, on the field or row level, gets invoked, the new row will still be visible to the user on the web page. Even if you invoke Ask method on the Transactions data view within one of the event handlers, the new row won't disappear from the webpage.
With all that said, the best and probably the only way to display popup exception and prevent the grid from inserting a new row is by replacing the standard Add New Row button on PXGrid with a custom action, which will first run the validation and display popup exception, if necessary. Otherwise, a new row will be inserted into PXGrid. It's also required to enable or disable the custom NewSOTran action based on the state of the standard PXGrid's Insert button.
public class SOOrderEntryExt : PXGraphExtension<SOOrderEntry>
{
public void SOOrder_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
NewSOTran.SetEnabled(Base.Transactions.AllowInsert);
}
public PXAction<SOOrder> NewSOTran;
[PXButton(CommitChanges = true)]
[PXUIField]
protected void newSOTran()
{
var listMissingOEdesc = new List<SOLine>();
var select = Base.Transactions.Select();
foreach (SOLine row in select)
{
var isOEDesc = !string.IsNullOrEmpty(row.TranDesc);
if (isOEDesc == true)
listMissingOEdesc.Add(row);
}
if (listMissingOEdesc.Count > 0)
{
throw new PXException("Cannot add a new line.");
}
var newTran = Base.Transactions.Insert();
Base.Transactions.Cache.ActiveRow = newTran;
}
}
In Aspx there will required 3 major chages:
SyncPositionWithGraph property set to True for PXGrid:
<px:PXGrid ID="grid" runat="server" DataSourceID="ds" Width="100%" TabIndex="100"
SkinID="DetailsInTab" StatusField="Availability" SyncPosition="True" Height="473px"
SyncPositionWithGraph="True" >
the standard AddNew action must be replaced by a custom NewSOTran action:
<ActionBar>
<Actions>
<AddNew ToolBarVisible ="False" />
</Actions>
<CustomItems>
<px:PXToolBarButton CommandName="NewSOTran" CommandSourceID="ds"
DisplayStyle="Image">
<Images Normal="main#AddNew" />
<ActionBar GroupIndex="0" Order="2" />
</px:PXToolBarButton>
...
</CustomItems>
</ActionBar>
AllowAddNew property set to false in the Mode section of PXGrid to prevent the standart Insert button from execution when users use keyboard shortcuts or double-click on PXGrid:
<Mode InitNewRow = "True" AllowFormEdit="True" AllowUpload="True" AllowDragRows="true"
AllowAddNew="false" />
To select new records’ first cell and switch it to the edit mode (unless the first cell is read-only), it's also required to subscribe to the Initialize and ToolsButtonClick client events of PXGrid:
<ClientEvents Initialize="initTransactionsGrid"
ToolsButtonClick="transactionsGriduttonClick" />
and define the following JavaScript functions:
var isInitEvents = false;
function initTransactionsGrid(a, b) {
if (isInitEvents) return;
isInitEvents = true;
a.events.addEventHandler("afterRepaint", editNewSOTran);
}
function editNewSOTran() {
if (lastActiveRowIndex != null) {
var grid = px_alls["grid"];
if (grid.activeRow) {
var activeRowIndex = grid.rows.indexOf(grid.activeRow);
if (activeRowIndex != lastActiveRowIndex) {
grid.activeRow.activateCell(0, false);
grid.beginEdit();
}
}
lastActiveRowIndex = null;
}
}
var lastActiveRowIndex;
function transactionsGriduttonClick(sender, args) {
if (args.button && args.button.commandName == "NewSOTran") {
if (sender.activeRow)
lastActiveRowIndex = sender.rows.indexOf(sender.activeRow);
else
lastActiveRowIndex = -1;
return;
}
lastActiveRowIndex = null;
}
To package custom JavaScript code into customization, in Layout Editor you can drag and drop a Java Script element from the Add Controls tab and copy your entire JavaScript code into the Script property.

How to prevent displaying True/False in column when using Image?

I would like to have an image in column for boolean type. To specify column properties, I use OLVColumn attribute and there I specify ImageAspectName.
[OLVColumn("UseK", DisplayIndex = 4, ImageAspectName = "ImageForUseK", CheckBoxes = false, Width = 40)]
public bool UseK
{
get { return useK; }
set
{
if (useK == value) return;
useK = value;
OnPropertyChanged("UseK");
}
}
protected bool useK = true;
public string ImageForUseK()
{
return "success";
}
This works fine and displaying image in column, but also displaying literal "True" next to image.
How can I avoid displaying string value of boolean property, while still using ImageAspectName?
You could set AspectToStringFormat to a space.

Expand/Collapse Programmatically in Radgrid

I am using RadGrid with Nested Hierarchy of Master/Detail Tables. I want to Expand the Master Row when the detail Table inside the row has few rows. I am trying to achieve the same using below code
Private Sub RadGrid_ItemDataBound(ByVal sender As System.Object, ByVal e As Telerik.Web.UI.GridItemEventArgs) Handles dbgView.ItemDataBound
If <considtion to check if row is expanded>Then
e.Item.Expanded = True
End If
However even after setting the Expanded flag as True, if I check the value of the state in QuickWatch, it still remains False. Can someone help me understand why state for that specific row is not getting changed? If this is not the right way in changing the state programmatically, can someone let me know the alternate way?
Try to rebind the grid after setting the Expanded property or simply move the condition in the Page_Load method. Just make sure that after the changing of the value, there is rebind or the NeedDataSource method is executed.
Hope these suggestions help.
For resolving the issue , i used two hidden fields
<asp:HiddenField ID="hdnExpandCollapse" Value="0" runat="server" />
<asp:HiddenField ID="hdnExpanded" Value="0" runat="server" />
Then the following two grid events are used to capture the state of the grid item
/* Start functions used for collapse the grid */
protected void Grid_PreRender(object sender, EventArgs e)
{
int i = 0;
foreach (GridDataItem item in Grid.MasterTableView.Items)
{
GridTableView DetailsTable = (GridTableView)item.OwnerTableView;
System.Collections.Hashtable ht = DetailsTable.DataKeyValues[i];
string strDataKey= ht["DataKey"].ToString();
if (strDataKey == hdnExpandCollapse.Value)
{
if (hdnExpanded.Value == strDataKey)
{
item.Expanded = false;
hdnExpanded.Value = "0";
}
else
{
item.Expanded = true;
hdnExpanded.Value = strDataKey;
}
}
i++;
}
}
protected void Grid_ItemCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
{
if (e.CommandName == RadGrid.ExpandCollapseCommandName)
{
hdnExpandCollapse.Value = ((EntityClass)(e.Item.DataItem)).DataKey.ToString();
}
}
/* End functions used for collapse the grid */
Reply

javafx column in tableview auto fit size

afaik The TableView in javafx have 2 column resize policies: CONSTRAINED_RESIZE_POLICY and UNCONSTRAINED_RESIZE_POLICY, but I want columns is resized to fit the content of theirs cells
I think it's a simple problem in other platform (like datagridview in C#) but can not resolve
After 3 years I come back to this problem again, some suggestions are calculating the size of text of data in each cell (it's complicated depending on font size, font family, padding...)
But I realize that when I click on the divider on table header, it's resized fit to content as I want. So I dig into JavaFX source code I finally found resizeColumnToFitContent method in TableViewSkin, but it is protected method, we can resolve by reflection:
import com.sun.javafx.scene.control.skin.TableViewSkin;
import javafx.scene.control.Skin;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class GUIUtils {
private static Method columnToFitMethod;
static {
try {
columnToFitMethod = TableViewSkin.class.getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class);
columnToFitMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public static void autoFitTable(TableView tableView) {
tableView.getItems().addListener(new ListChangeListener<Object>() {
#Override
public void onChanged(Change<?> c) {
for (Object column : tableView.getColumns()) {
try {
columnToFitMethod.invoke(tableView.getSkin(), column, -1);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
});
}
}
Note that we call "tableView.getItems()" so we have to call this function after setItems()
After testing the previous solutions I finally found one that worked for me.
So here is mine (call the method after inserting the data into table):
public static void autoResizeColumns( TableView<?> table )
{
//Set the right policy
table.setColumnResizePolicy( TableView.UNCONSTRAINED_RESIZE_POLICY);
table.getColumns().stream().forEach( (column) ->
{
//Minimal width = columnheader
Text t = new Text( column.getText() );
double max = t.getLayoutBounds().getWidth();
for ( int i = 0; i < table.getItems().size(); i++ )
{
//cell must not be empty
if ( column.getCellData( i ) != null )
{
t = new Text( column.getCellData( i ).toString() );
double calcwidth = t.getLayoutBounds().getWidth();
//remember new max-width
if ( calcwidth > max )
{
max = calcwidth;
}
}
}
//set the new max-widht with some extra space
column.setPrefWidth( max + 10.0d );
} );
}
I think just by overriding a call back function that returns true will solve your problem it will disable the re-sizing of columns and all columns will be re-sized to fit the content of their cells.
Example:
TableView<String[]> table = new TableView<>();
table.setColumnResizePolicy(new Callback<TableView.ResizeFeatures, Boolean>() {
#Override
public Boolean call(ResizeFeatures p) {
return true;
}
});
If you want that only one column fills the remaining width of a table, I have found a pretty straight forward solution, which is short and does not require the hacky reflection solution described above:
DoubleBinding usedWidth = columnA.widthProperty().add(columnB.widthProperty()).add(columnC.widthProperty());
fillingColumn.prefWidthProperty().bind(tableView.widthProperty().subtract(usedWidth));
Or to make it short:
// automatically adjust width of columns depending on their content
configAttributeTreeTable.setColumnResizePolicy((param) -> true );
I have used the other solutions on this question, and it works pretty good. However, the downside of this is when the width of the TableView is greater than the required width of the TableColumns together. I have created a hack to solve this problem, and it works OK:
orderOverview.setColumnResizePolicy((param) -> true );
Platform.runLater(() -> FXUtils.customResize(orderOverview));
where FXUtils.customResize() is created as follows:
public static void customResize(TableView<?> view) {
AtomicDouble width = new AtomicDouble();
view.getColumns().forEach(col -> {
width.addAndGet(col.getWidth());
});
double tableWidth = view.getWidth();
if (tableWidth > width.get()) {
TableColumn<?, ?> col = view.getColumns().get(view.getColumns().size()-1);
col.setPrefWidth(col.getWidth()+(tableWidth-width.get()));
}
}
I hope this could be helpful for other people as well!
This is the way I found :
tableview.setColumnResizePolicy( TableView.CONSTRAINED_RESIZE_POLICY );
idCol.setMaxWidth( 1f * Integer.MAX_VALUE * 50 ); // 50% width
nameCol.setMaxWidth( 1f * Integer.MAX_VALUE * 30 ); // 30% width
ageCol.setMaxWidth( 1f * Integer.MAX_VALUE * 20 ); // 20% width
This code autoresizes all column widths in relational proportions to the table width,
while it can fix the first column width to a given value when table width is lower than x
// To generalize the columns width proportions in relation to the table width,
// you do not need to put pixel related values, you can use small float numbers if you wish,
// because it's the relative proportion of each columns width what matters here:
final float[] widths = { 1.2f, 2f, 0.8f };// define the relational width of each column
// whether the first column should be fixed
final boolean fixFirstColumm = true;
// fix the first column width when table width is lower than:
final float fixOnTableWidth = 360; //pixels
// calulates sum of widths
float sum = 0;
for (double i : widths) {
sum += i;
}
// calculates the fraction of the first column proportion in relation to the sum of all column proportions
float firstColumnProportion = widths[0] / sum;
// calculate the fitting fix width for the first column, you can change it by your needs, but it jumps to this width
final float firstColumnFixSize = fixOnTableWidth * firstColumnProportion;
// set the width to the columns
for (int i = 0; i < widths.length; i++) {
table.getColumns().get(i).prefWidthProperty().bind(table.widthProperty().multiply((widths[i] / sum)));
// ---------The exact width-------------^-------------^
if (fixFirstColumm)
if (i == 0) {
table.widthProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> arg0, Number oldTableWidth, Number newTableWidth) {
if (newTableWidth.intValue() <= fixOnTableWidth) {
// before you can set new value to column width property, need to unbind the autoresize binding
table.getColumns().get(0).prefWidthProperty().unbind();
table.getColumns().get(0).prefWidthProperty().setValue(firstColumnFixSize);
} else if (!table.getColumns().get(0).prefWidthProperty().isBound()) {
// than readd the autoresize binding if condition table.width > x
table.getColumns().get(0).prefWidthProperty()
.bind(table.widthProperty().multiply(firstColumnProportion));
}
}
});
}
}
advice to put the code in an separated TableAutoresizeModel class, there you can handle further calculations, for example on hiding columns add listener...
#HarleyDavidson 's answer in kotlin
val String.fxWidth: Double
get() = Text(this).layoutBounds.width
// call the method after inserting the data into table
fun <T> TableView<T>.autoResizeColumns() {
columnResizePolicy = TableView.UNCONSTRAINED_RESIZE_POLICY
columns.forEach { column ->
column.setPrefWidth(
(((0 until items.size).mapNotNull {
column.getCellData(it)
}.map {
it.toString().fxWidth
}.toMutableList() + listOf(
column.text.fxWidth
)).maxOrNull() ?: 0.0) + 10.0
)
}
}
This will set the minimum width of columns based on the font and the text, so that the column names wont be cropped.
public static void setDataTableMinColumnWidth(TableView<?> dataTable)
{
for (Node columnHeader : dataTable.lookupAll(".column-header"))
{
var columnString = columnHeader.getId();
if (columnString != null)
{
for (Node columnHeaderLabel : columnHeader.lookupAll(".label"))
{
var tableColumn = dataTable.getColumns()
.stream()
.filter(x -> x.getId()
.equals(columnString))
.findFirst();
if (columnHeaderLabel instanceof Label && tableColumn.isPresent())
{
var label = (Label) columnHeaderLabel;
/* calc text width based on font */
var theText = new Text(label.getText());
theText.setFont(label.getFont());
var width = theText.getBoundsInLocal()
.getWidth();
/*
* add 10px because of paddings/margins for the button
*/
tableColumn.get()
.setMinWidth(width + 10);
}
}
}
}
}
How to use:
dataTable.needsLayoutProperty()
.addListener((obs, o, n) -> setDataTableMinColumnWidth(dataTable));
For the Columns, the id property needs to be set first:
TableColumn<BundImportTask, String> columnTask = new TableColumn<>("My Column");
columnTask.setId("MyColumnId");
columnTask.setCellValueFactory(data -> new SimpleStringProperty(data.getValue()
.fileName()));
I implemented a solution that it's fairly more complicated than the ones that I found here, but that allows a specific column to be resized by double clicking on the header, while still letting the user resize columns manually.
This is achieved by listening to click events on the header of the table (TableHeaderRow). When a double click occurs, the specific column header is found by matching the mouse event X and Y.
Note: to make this work it's necessary that each column has an ID set.
// when skin is loaded (hence css), setup click listener on header to make column fit to content max width on double click
tableView.skinProperty().addListener((a, b, newSkin) -> {
TableHeaderRow headerRow = (TableHeaderRow) tableView.lookup("TableHeaderRow");
NestedTableColumnHeader headers = (NestedTableColumnHeader) (headerRow.getChildren().get(1));
headerRow.setOnMouseClicked(evt -> {
if (evt.getClickCount() != 2 || evt.getButton() != MouseButton.PRIMARY) return;
// find the header column that contains the click
for (TableColumnHeader header : headers.getColumnHeaders()) {
if (header.contains(header.parentToLocal(evt.getX(), evt.getY()))) {
fitColumnWidthToContent(header.getId());
}
}
evt.consume();
});
});
The method that takes care of the resizing is the following:
private void fitColumnWidthToContent (String colId) {
// find column matching id
TableColumn column = null;
for (TableColumn tempCol : tableView.getColumns()) {
if (tempCol.getId().equals(colId)) {
column = tempCol;
break;
}
}
if (column == null) {
throw new IllegalStateException("Column ID doesn't match any actual column");
}
// set default width to column header width
Text text = new Text(column.getText());
double max = text.getLayoutBounds().getWidth();
for (int i = 0; i < tableView.getItems().size(); i++ ) {
if (column.getCellData(i) == null) continue;
text = new Text(column.getCellData(i).toString());
double textWidth = text.getLayoutBounds().getWidth();
if (textWidth > max) {
max = textWidth;
}
}
column.setPrefWidth(max + 12);
}
I hope this can be useful to anyone.
In order to allow also manual resizing, it's necessary to add a bit more code on table initalization:
// listen to width changes in columns and set to pref width (otherwise if for example width changes because of
// user resizing the column, applying the old pref width won't work because it stayed the same)
for (TableColumn col : tableView.getColumns()) {
col.widthProperty().addListener((obs, oldVal, newVal) -> {
col.setPrefWidth(newVal.doubleValue());
});
}
I have implemented a solution for TreeTableView. It is still in evolution but it manifests now promising results. Hereafter a description of the solution.
In the control skin class, I added to the control children the TreeTableView and an invisible VBox. A cell factory provide derived cells to the target TreeTableColumn. The derived cells wrap a Label node which is added or removed to the invisible VBox according to the empty property, and which its prefWidth is set according to the cell width. The cells make use of:
getProperties().put(Properties.DEFER_TO_PARENT_PREF_WIDTH, Boolean.TRUE)
I override the cell's computePrefWidth() method as follow:
#Override
protected double computePrefWidth(double height) {
return Double.max(_box.prefWidth(-1.0), super.computePrefWidth(height) + 24.0);
}
The Vbox width property is bind to the TreeTableColumn's prefWidth. This is required to resize as well the header of the column.
Is worth to note, that at the time being, to simplify the development of a solution, this approach works well with built in sort, order, and resize feature disabled. Ie.
_nameColumn = new TreeTableColumn<>("Name");
_nameColumn.setResizable(false);
_nameColumn.setReorderable(false);
_nameColumn.setSortable(false);
Happy coding
After long research. Best Solution is..
tblPlan.setColumnResizePolicy((param) -> true );
Platform.runLater(() -> customResize(tblPlan));
"Custom Resize"
public void customResize(TableView<?> view) {
AtomicLong width = new AtomicLong();
view.getColumns().forEach(col -> {
width.addAndGet((long) col.getWidth());
});
double tableWidth = view.getWidth();
if (tableWidth > width.get()) {
view.getColumns().forEach(col -> {
col.setPrefWidth(col.getWidth()+((tableWidth-width.get())/view.getColumns().size()));
});
}
}
<TableView fx:id="datalist" layoutX="30.0" layoutY="65.0" prefHeight="400.0" AnchorPane.bottomAnchor="100.0" AnchorPane.leftAnchor="30.0" AnchorPane.rightAnchor="30.0" AnchorPane.topAnchor="100.0">
<columns>
<TableColumn fx:id="number" minWidth="-1.0" prefWidth="-1.0" style="width: auto;" text="number" />
<TableColumn fx:id="id" minWidth="-1.0" prefWidth="-1.0" text="id" />
<TableColumn fx:id="name" minWidth="-1.0" prefWidth="-1.0" text="name" />
<TableColumn fx:id="action" minWidth="-1.0" prefWidth="-1.0" text="todo" />
</columns>
**<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>**
</TableView>

Resources