Related
I tried to implement bottom sheet for my Xamarin forms app. I have Implemented using couple of methods including nugets. In my main behind view I have a ListView. In the bottom sheet normal Frames and Labels. My problem is last one or two items not displaying or partially displaying in the ListView in almost all option.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:yummy="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
x:Class="RSMapp.Views.RSMview">
<ContentPage.ToolbarItems>
<ToolbarItem Name="MenuItem" Command="{Binding filterCommand}" Order="Primary" Icon="filter.png" Text="" Priority="0" IsEnabled="{Binding IsEnabled}" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<RelativeLayout>
<StackLayout BackgroundColor="#d4d4d4" x:Name="mainView" Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="70"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<yummy:PancakeView HeightRequest="55" BackgroundColor="{Binding mainBgColor}" Padding="10" HorizontalOptions="FillAndExpand" x:Name="dropdownLayout" CornerRadius="0,0,15,15" VerticalOptions="CenterAndExpand" Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="AUTO"/>
</Grid.ColumnDefinitions>
<Frame IsVisible="{Binding isMonthVisible}" HasShadow="{OnPlatform Android=true, iOS=false}" HorizontalOptions="FillAndExpand" BackgroundColor="WhiteSmoke" Padding="10,0,10,0" CornerRadius="15" Grid.Column="0">
<Picker
Title="{Binding SelectedItem.mName}"
IsVisible="{Binding isMonthVisible}"
TitleColor="Black"
VerticalTextAlignment="Center"
Margin="0,0,20,0"
Focused="Picker_Focused"
TextColor="#565656"
ItemsSource="{Binding MyList}"
SelectedItem="{Binding SelectedItem}"
ItemDisplayBinding="{Binding mName}" />
</Frame>
<StackLayout WidthRequest="60" IsVisible="{Binding extraBtnVisible}" VerticalOptions="Center" HorizontalOptions="Center" Grid.Column="1">
<ImageButton HeightRequest="50" WidthRequest="30" Command="{Binding regionClassCommand}" VerticalOptions="Center" IsVisible="{Binding extraBtnVisible}" BackgroundColor="#F44336" Source="extra.png"/>
</StackLayout>
</Grid>
</yummy:PancakeView>
<StackLayout BackgroundColor="#d4d4d4" Grid.Row="1" Orientation="Vertical">
<ListView IsVisible="{Binding hasLifeData}" ItemTapped="RSMListView_ItemTapped"
SeparatorVisibility="None"
IsPullToRefreshEnabled="False"
ItemsSource="{Binding rsmLifeRankingList}"
x:Name="RSMListView"
Margin="0,0,0,2"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame Margin="2,4,2,4" BackgroundColor="White" IsVisible="True" HasShadow="{OnPlatform Android='true',iOS='false'}" CornerRadius="10" Padding="2,4,2,4">
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="White" Orientation="Vertical">
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout IsVisible="{Binding noData}" HorizontalOptions="CenterAndExpand" VerticalOptions="StartAndExpand">
<Image Source="nodata" HorizontalOptions="Center"/>
</StackLayout>
</StackLayout>
</Grid>
</StackLayout>
<yummy:PancakeView CornerRadius="10,10,0,0" Padding="0" BackgroundColor="#faf9f8"
x:Name="bottomSheet" RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,Factor=.96,Constant=0}" RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Width,Factor=1,Constant=0}" RelativeLayout.HeightConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Height,Factor=1,Constant=0}">
<yummy:PancakeView.GestureRecognizers>
<PanGestureRecognizer PanUpdated="OnPanUpdated" />
</yummy:PancakeView.GestureRecognizers>
<StackLayout BackgroundColor="Gray" Spacing="0">
<BoxView HeightRequest="5" CornerRadius="2" Margin="0,6,0,8" WidthRequest="80" BackgroundColor="LightGray" HorizontalOptions="Center"/>
<StackLayout Orientation="Vertical">
<StackLayout IsVisible="{Binding hasLifeData}" BackgroundColor="WhiteSmoke" Orientation="Vertical" Grid.Row="1">
<StackLayout IsVisible="{Binding layoutVisible}" Spacing="0" Orientation="Vertical">
<yummy:PancakeView Padding="10,0,10,10" CornerRadius="0,0,15,15" BackgroundColor="{StaticResource colorLife}">
<StackLayout Orientation="Vertical">
</StackLayout>
</yummy:PancakeView>
<ScrollView Padding="0,5,0,5">
<StackLayout Margin="2,0,2,0" Orientation="Vertical">
</StackLayout>
</ScrollView>
</StackLayout>
</StackLayout>
</StackLayout>
</StackLayout>
</yummy:PancakeView>
</RelativeLayout>
</ContentPage.Content>
</ContentPage>
Code behind
public partial class RSMview : ContentPage
{
private RSMViewModel vm;
private string company;
private string lifColor = "#f2b22c";
private double x, y;
public RSMview()
{
InitializeComponent();
}
public RSMview(string company, string userRegion)
{
InitializeComponent();
this.company = company;
BindingContext = new RSMViewModel();
vm = BindingContext as RSMViewModel;
Title = userRegion + " (RSM)";
ToolbarStatusBarTheme.ToolbarWithStatusBar(company);
if (NetworkCheck.IsInternet())
{
if (company.Equals("G"))
{
dropdownLayout.BackgroundColor = Color.FromHex(genColor);
vm.GetGenRSMData(userRegion, "G");
}
else if (company.Equals("L"))
{
dropdownLayout.BackgroundColor = Color.FromHex(lifColor);
vm.GetLifeRSMData(userRegion, "L");
}
}
}
private async void RSMListView_ItemTapped(object sender, ItemTappedEventArgs e)
{
var item = (LifeRSMData)e.Item;
await Navigation.PushAsync(new SMviewHead(company, item));
}
protected override void OnAppearing()
{
base.OnAppearing();
if (Device.Idiom == TargetIdiom.Phone)
{
CrossDeviceOrientation.Current.LockOrientation(Plugin.DeviceOrientation.Abstractions.DeviceOrientations.Portrait);
}
}
void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
// Handle the pan
switch (e.StatusType)
{
case GestureStatus.Running:
// Translate and ensure we don't y + e.TotalY pan beyond the wrapped user interface element bounds.
var translateY = Math.Max(Math.Min(0, y + e.TotalY), -Math.Abs((Height * .25) - Height));
bottomSheet.TranslateTo(bottomSheet.X, translateY, 20);
break;
case GestureStatus.Completed:
// Store the translation applied during the pan
y = bottomSheet.TranslationY;
//at the end of the event - snap to the closest location
var finalTranslation = Math.Max(Math.Min(0, -1000), -Math.Abs(GetClosestLockState(e.TotalY + y)));
//depending on Swipe Up or Down - change the snapping animation
if (isSwipeUp(e))
{
bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 250, Easing.SpringIn);
}
else
{
bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 250, Easing.SpringOut);
}
//dismiss the keyboard after a transition
//SearchBox.Unfocus();
y = bottomSheet.TranslationY;
break;
}
}
public bool isSwipeUp(PanUpdatedEventArgs e)
{
if (e.TotalY < 0)
{
return true;
}
return false;
}
//TO-DO: Make this cleaner
private double GetClosestLockState(double TranslationY)
{
//Play with these values to adjust the locking motions - this will change depending on the amount of content ona apge
var lockStates = new double[] { 0, .5, .88 };
//get the current proportion of the sheet in relation to the screen
var distance = Math.Abs(TranslationY);
var currentProportion = distance / Height;
//calculate which lockstate it's the closest to
var smallestDistance = 10000.0;
var closestIndex = 0;
for (var i = 0; i < lockStates.Length; i++)
{
var state = lockStates[i];
var absoluteDistance = Math.Abs(state - currentProportion);
if (absoluteDistance < smallestDistance)
{
smallestDistance = absoluteDistance;
closestIndex = i;
}
}
var selectedLockState = lockStates[closestIndex];
var TranslateToLockState = GetProportionCoordinate(selectedLockState);
return TranslateToLockState;
}
private double GetProportionCoordinate(double proportion)
{
return proportion * Height;
}
private void DismissBottomSheet()
{
//SearchBox.Unfocus();
var finalTranslation = Math.Max(Math.Min(0, -1000), -Math.Abs(GetProportionCoordinate(0)));
bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 450, Easing.SpringOut);
//SearchBox.Text = string.Empty;
}
private void Picker_Focused(object sender, FocusEventArgs e)
{
DismissBottomSheet();
}
private void OpenBottomSheet()
{
var finalTranslation = Math.Max(Math.Min(0, -1000), -Math.Abs(GetProportionCoordinate(.85)));
bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 150, Easing.SpringIn);
}
}
ViewModel
public class RSMViewModel : BaseViewModelHelper
{
public RSMViewModel()
{
btnImage = "upbtn.png";
extraBtnVisible = false;
isKpiEnable = false;
}
private void CreateToplayout(string company, string sList)
{
if (company.Equals("L"))
{
if (sList != null)
{
var itemList = JsonConvert.DeserializeObject<List<SummaryLifeRegionalData>>(sList);
//var itemList = mList.rsmLifeData;
if (itemList.Count > 0)
{
foreach (var item in itemList)
{
FYR_NOP_TO_BE_PAID = item.FYR_NOP_TO_BE_PAID.ToString();
....
}
}
else
{
}
}
else
{
}
}
else if (company.Equals("G"))
{
if (sList != null)
{
var mList = JsonConvert.DeserializeObject<SummaryRegionalHeaderData>(sList);
var itemList = mList.rsmMotorData;
if (itemList.Count > 0)
{
foreach (var item in itemList)
{
RENEWAL_VEHICLE_COUNT = item.RENEWAL_VEHICLE_COUNT.ToString();
....
}
}
else
{
}
}
else
{
}
}
}
public void GetLifeRSMData(string p_region, string cType)
{
extraBtnVisible = false;
this.p_region = p_region;
this.companyType = cType;
IsEnabled = false;
SelectedItem = getCurrentMonth(cType);
}
public MonthData SelectedItem
{
get => _selectedItem;
set
{
_selectedItem = value;
Task.Run(async () =>
{
AcrDialogClass.ShowLoadingDialog("Loading...");
if (firstRun)
{
string selectedSelectedItem = _selectedItem.ToString();
string getSubStringMonth = selectedSelectedItem.Substring(1, 2);
string getSubStringYear = selectedSelectedItem.Substring(9, 4);
await ChangeListAsync(getSubStringYear, getSubStringMonth, p_region, companyType);
string sList = null;
if (companyType.Equals("L"))
{
mainBgColor = "#f2b22c";
sList = await _apiServices.GetLifeSummaryDataRM(getSubStringYear, getSubStringMonth, p_region);
}
else if (companyType.Equals("G"))
{
mainBgColor = "#F44336";
sList = await _apiServices.getRSMsummaryData(getSubStringYear, getSubStringMonth, p_region, null);
}
CreateToplayout(companyType, sList);
}
else
{
firstRun = true;
}
AcrDialogClass.HideLoadingDialog();
});
OnPropertyChanged();
}
}
private async Task ChangeListAsync(string getSubStringYear, string getSubStringMonth, string p_region, string companyType)
{
if (companyType.Equals("L"))
{
kpiImage = "kpi_chart.png";
isKpiEnable = false;
IsEnabled = false;
//lifeValue = await _apiServices.getLifeRSMDataList(getSubStringYear, getSubStringMonth, p_region, authenticateData1);
lifeValue = await _apiServices.GetLifeRSMDataList(getSubStringYear, getSubStringMonth, p_region);
if (lifeValue != null)
{
hasLifeData = true;
hasGenData = false;
noData = false;
IsEnabled = true;
layoutVisible = true;
layoutVisibleGen = false;
foreach (LifeRSMData ss in lifeValue)
{
ss.TOTAL_PREM_TO_BE_PAID_STRING = ss.TOTAL_PREM_TO_BE_PAID.ToString("N", CultureInfo.InvariantCulture);
ss.LIFE_TARGET_S = ss.LIFE_TARGET.ToString("N", CultureInfo.InvariantCulture);
ss.LIFE_ACHIVEMENT_S = ss.LIFE_ACHIVEMENT.ToString("N", CultureInfo.InvariantCulture);
Device.BeginInvokeOnMainThread(() =>
{
createChart(ss);
});
}
rsmLifeRankingList = lifeValue;
}
else
{
hasLifeData = false;
hasGenData = false;
noData = true;
IsEnabled = false;
layoutVisible = false;
layoutVisibleGen = false;
rsmLifeRankingList.Clear();
}
}
else if (companyType.Equals("G"))
{
kpiImage = "kpi_chart.png";
isKpiEnable = false;
IsEnabled = false;
genValue = await _apiServices.getGenRSMDataList(getSubStringYear, getSubStringMonth, p_region, null);
if (genValue != null)
{
hasGenData = true;
hasLifeData = false;
noData = false;
IsEnabled = true;
layoutVisible = false;
layoutVisibleGen = true;
foreach (GenRSMData ss in genValue)
{
ss.RENEWAL_PREMIUM_TO_BE_PAID_S = ss.RENEWAL_PREMIUM_TO_BE_PAID.ToString("N", CultureInfo.InvariantCulture);
ss.GENERAL_TARGET_S = ss.GENERAL_TARGET.ToString("N", CultureInfo.InvariantCulture);
ss.GENERAL_ACHIVEMENT_S = ss.GENERAL_ACHIVEMENT.ToString("N", CultureInfo.InvariantCulture);
createChartGen(ss);
}
rsmGenRankingList = genValue;
}
else
{
hasGenData = false;
hasLifeData = false;
noData = true;
IsEnabled = false;
layoutVisible = false;
layoutVisibleGen = false;
rsmGenRankingList.Clear();
}
}
else
{
}
}
private void createChart(LifeRSMData ss)
{
var labels = new List<string>();
var lineEntries = new List<EntryChart>();
float achPercentg = (float)((ss.LIFE_ACHIVEMENT / ss.LIFE_TARGET) * 100);
lineEntries.Add(new EntryChart(0, 100));
lineEntries.Add(new EntryChart(1, achPercentg));
labels.Add("Tar:");
labels.Add("Ach:");
var lineDataSet4 = new BarDataSet(lineEntries, "")
{
Colors = new List<Color>{
Color.FromHex("#248acf"), Color.FromHex("#36DBBB")
}
};
var lineData4 = new BarChartData(new List<IBarDataSet>() { lineDataSet4 });
AxisLeft = new YAxisConfig();
AxisLeft.DrawGridLines = false;
AxisLeft.DrawAxisLine = true;
AxisLeft.Enabled = true;
AxisLeft.AxisMinimum = 0;
AxisLeft.AxisMaximum = 100;
AxisRight = new YAxisConfig();
AxisRight.DrawAxisLine = false;
AxisRight.DrawGridLines = false;
AxisRight.Enabled = false;
XAxis = new XAxisConfig();
XAxis.Granularity = 1f;
XAxis.XAXISPosition = XAXISPosition.BOTTOM;
XAxis.DrawGridLines = false;
XAxis.DrawLabels = true;
XAxis.AxisValueFormatter = new TextByIndexXAxisFormatter(labels);
Legend = new LegendXF();
Legend.Enabled = false;
DescriptionChart = new ChartDescription();
DescriptionChart.Enabled = false;
DescriptionChart.Text = "";
ss.AxisLeft = AxisLeft;
ss.AxisRight = AxisRight;
ss.XAxis = XAxis;
ss.Legend = Legend;
ss.DescriptionChart = DescriptionChart;
ss.chartData = lineData4;
}
public ICommand filterCommand
{
get
{
return new Command(() =>
{
if (IsEnabled)
{
if (companyType != null)
{
if (companyType.Equals("L"))
{
UserDialogs.Instance.ActionSheet(new ActionSheetConfig().SetTitle("Sort using...")
.Add("Due", () => this.SortData("DueA", companyType), "fup.png")
.Add("Due", () => this.SortData("DueD", companyType), "fdown.png")
.Add("Achievement", () => this.SortData("AchA", companyType), "fup.png")
.Add("Achievement", () => this.SortData("AchD", companyType), "fdown.png").SetUseBottomSheet(true));
}
else if (companyType.Equals("G"))
{
UserDialogs.Instance.ActionSheet(new ActionSheetConfig().SetTitle("Sort using...")
.Add("Due", () => this.SortData("DueA", companyType), "fup.png")
.Add("Due", () => this.SortData("DueD", companyType), "fdown.png").SetUseBottomSheet(true));
}
}
}
});
}
}
public ICommand regionClassCommand
{
get
{
return new Command(() =>
{
Application.Current.MainPage.Navigation.PushAsync(new RSMclassView(p_region, SelectedItem));
});
}
}
private void SortData(string caseSwitch, string companyType)
{
}
private MonthData getCurrentMonth(string cType)
{
DateTime now = DateTime.Now;
string currMonth_2 = now.AddMonths(-2).ToString("(MM)/MMM yyyy");
string currMonth_1 = now.AddMonths(-1).ToString("(MM)/MMM yyyy");
string currMonth0 = now.ToString("(MM)/MMM yyyy");
string currMonth1 = now.AddMonths(1).ToString("(MM)/MMM yyyy");
if (cType.Equals("L"))
{
MyList.Add(new MonthData { mName = currMonth_2 });
MyList.Add(new MonthData { mName = currMonth_1 });
MyList.Add(new MonthData { mName = currMonth0 });
MyList.Add(new MonthData { mName = currMonth1 });
}
else
{
MyList.Add(new MonthData { mName = currMonth_2 });
MyList.Add(new MonthData { mName = currMonth_1 });
MyList.Add(new MonthData { mName = currMonth0 });
}
return new MonthData { mName = currMonth0 };
}
}
You can set the ListView to appear above the bottom frame.
Please remove the outer element of the ItemListView and add the following properties for ItemListView:
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant, Constant=0}"
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant, Constant=0}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1.0}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1.0}"
The whole code is :
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="Yellow"
x:Class="TestBottomSheet.MainPage">
<RelativeLayout>
<ListView x:Name="ItemListView" HasUnevenRows="true"
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant, Constant=0}"
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant, Constant=0}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1.0}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.91}"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame HasShadow="True" BackgroundColor="White" CornerRadius="15" Margin="5">
<StackLayout Orientation="Vertical">
<Label Text="{Binding title}" FontSize="Medium"/>
<Label Text="{Binding id}" FontSize="Default"/>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Frame HasShadow="true" CornerRadius="8" Padding="1,4,1,0" BackgroundColor="#faf9f8"
x:Name="bottomSheet" RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,Factor=.92,Constant=0}" RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Width,Factor=1,Constant=0}" RelativeLayout.HeightConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Height,Factor=1,Constant=0}">
<Frame.GestureRecognizers>
<PanGestureRecognizer PanUpdated="OnPanUpdated" />
</Frame.GestureRecognizers>
<StackLayout Spacing="5">
<BoxView HeightRequest="5" CornerRadius="2" WidthRequest="50" BackgroundColor="Gray" HorizontalOptions="Center"/>
<StackLayout BackgroundColor="White" HeightRequest="25">
</StackLayout>
<ListView x:Name="ItemListView2" HasUnevenRows="true" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame HasShadow="True" BackgroundColor="FloralWhite" CornerRadius="15" Margin="5">
<StackLayout Orientation="Vertical">
<Label Text="{Binding id}" FontSize="Default"/>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Frame>
</RelativeLayout>
</ContentPage>
The result is:
I'm trying to adapt a Chart model (lineChart) with JavaFX, at first based on this link model:
https://docs.oracle.com/javafx/2/charts/line-chart.htm
My problem is showing the X-Axis values (Months in my case)
I've tried to make it more dynamic, based on these other links, but it still didn't work ...
//JavaFX Adding multiple XYChart.Series to LineChart without explicating declaring each series
//How to plot multiple series with javafx line chart which is in array list
Finally, based on this link, I was able to build a dynamic graph, which creates series to represent Month / Year of a collection movement:
//Is it possible to create an array of XYChart.Series on JavaFX?
I have a "small" detail that I couldn't solve yet, the models are created "scene" directly, without XML, this way it works normal.
But I would like to create with XML (I am using the Scene Builder to assemble the XML), to put more details on the screen, such as a TableView, etc.
As I mentioned above, the problem is that when I use the graph with XML, it does not show the values of the X Axis (Months in my case) it is "all in one column" ...
I hope you managed to explain ... I will leave the example that trying to adapt here, any help, thank you in advance.
I'll leave the sample program (simpler, not the one that assembles dynamically, to try to illustrate better).
"Scene" call class
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class LineChartExemplo extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
FXML file
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="579.0" prefWidth="918.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.171" fx:controller="linechartexemplo.FXMLDocumentController">
<children>
<Button fx:id="button" layoutX="14.0" layoutY="14.0" onAction="#handleButtonAction" text="Visualizar Gráfico" />
<Label fx:id="label" layoutX="135.0" layoutY="14.0" minHeight="16" minWidth="69" prefHeight="25.0" prefWidth="710.0" />
<LineChart fx:id="lineChart" layoutX="14.0" layoutY="52.0" prefHeight="512.0" prefWidth="887.0" title="Exemplo Gŕafico">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
</children>
</AnchorPane>
Controller class
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
public class FXMLDocumentController implements Initializable {
#FXML private Label label;
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
//final LineChart<String,Number> lineChart = new LineChart<String,Number>(xAxis,yAxis);
//#FXML private LineChart<String, Number> lineChart;
#FXML private LineChart<String, Number> lineChart = new LineChart<String,Number>(xAxis,yAxis);
#FXML
private void handleButtonAction(ActionEvent event) {
label.setText("Teste Gráfico...");
visualizaGrafico();
}
#Override
public void initialize(URL url, ResourceBundle rb) {
}
private void visualizaGrafico(){
lineChart.setTitle("Exemplo Gráfico");
yAxis.setLabel("Valores");
xAxis.setLabel("Meses");
XYChart.Series series = new XYChart.Series();
series.setName("Ano: 2018");
series.getData().add(new XYChart.Data("Jan", 23));
series.getData().add(new XYChart.Data("Feb", 14));
series.getData().add(new XYChart.Data("Mar", 15));
series.getData().add(new XYChart.Data("Apr", 24));
series.getData().add(new XYChart.Data("May", 34));
series.getData().add(new XYChart.Data("Jun", 36));
series.getData().add(new XYChart.Data("Jul", 22));
series.getData().add(new XYChart.Data("Aug", 45));
series.getData().add(new XYChart.Data("Sep", 43));
series.getData().add(new XYChart.Data("Oct", 17));
series.getData().add(new XYChart.Data("Nov", 29));
series.getData().add(new XYChart.Data("Dec", 25));
XYChart.Series series2 = new XYChart.Series();
series2.setName("Ano: 2019");
series2.getData().add(new XYChart.Data("Jan", 28));
series2.getData().add(new XYChart.Data("Feb", 17));
series2.getData().add(new XYChart.Data("Mar", 19));
series2.getData().add(new XYChart.Data("Apr", 14));
series2.getData().add(new XYChart.Data("May", 20));
series2.getData().add(new XYChart.Data("Jun", 42));
series2.getData().add(new XYChart.Data("Jul", 27));
series2.getData().add(new XYChart.Data("Aug", 48));
series2.getData().add(new XYChart.Data("Sep", 47));
series2.getData().add(new XYChart.Data("Oct", 19));
series2.getData().add(new XYChart.Data("Nov", 39));
series2.getData().add(new XYChart.Data("Dec", 29));
lineChart.getData().addAll(series, series2);
}
}
Print the chart to better illustrate.
Graph without using XML (OK with Database)
It looks like there is a bug somewhere that prevents this working properly when the chart is animated. Turn off animation in the chart with
#Override
public void initialize(URL url, ResourceBundle rb) {
lineChart.setAnimated(false);
}
There are additional issues with your code:
Never initialize fields annotated #FXML in your controller. The objects these fields are supposed to refer to are created according to the FXML code by the FXMLLoader, and are initialized in the controller by injection.
It's also unclear why you are creating a second set of axes in the controller, when you have already defined the axes in the FXML file.
Replace this code:
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
#FXML private LineChart<String, Number> lineChart = new LineChart<String,Number>(xAxis,yAxis);
with
#FXML private CategoryAxis xAxis ;
#FXML private NumberAxis yAxis ;
#FXML private LineChart<String, Number> lineChart ;
and add fx:ids to the axes in the FXML file so that they are properly injected into the controller:
<LineChart fx:id="lineChart" layoutX="14.0" layoutY="52.0" prefHeight="512.0" prefWidth="887.0" title="Exemplo Gŕafico">
<xAxis>
<CategoryAxis fx:id="xAxis" side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis fx:id="yAxis" side="LEFT" />
</yAxis>
</LineChart>
I'll put the solution code here, it can be useful for other people later.
I'm using SQL Server for Database (2012) and NetBeanas to develop ...
Class to start the scene
package graficos;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Graficos extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLGraficos.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
FXMLGraficos File
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.BarChart?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.chart.PieChart?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.effect.DropShadow?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="701.0" prefWidth="1407.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="graficos.FXMLGraficosController">
<children>
<AnchorPane layoutX="7.0" layoutY="152.0" prefHeight="254.0" prefWidth="361.0" style="-fx-background-color: #F5F5F5;">
<children>
<PieChart fx:id="pieChart" layoutX="7.0" prefHeight="254.0" prefWidth="355.0" title="Gráfico Movimento" />
</children>
<effect>
<DropShadow />
</effect>
</AnchorPane>
<AnchorPane layoutX="6.0" layoutY="14.0" prefHeight="131.0" prefWidth="363.0" style="-fx-background-color: #F5F5F5;">
<effect>
<DropShadow />
</effect>
<children>
<DatePicker fx:id="dtpInicial" layoutX="5.0" layoutY="43.0" prefHeight="25.0" prefWidth="106.0" />
<Label layoutX="5.0" layoutY="24.0" text="Data Inicial:" />
<DatePicker fx:id="dtpFinal" layoutX="124.0" layoutY="43.0" prefHeight="25.0" prefWidth="106.0" />
<Label layoutX="124.0" layoutY="24.0" text="Data Final:" />
<Button fx:id="btnOK" layoutX="247.0" layoutY="43.0" mnemonicParsing="false" onAction="#verificaData" prefHeight="34.0" prefWidth="61.0" text="OK" />
<Label fx:id="lblData" layoutX="12.0" layoutY="86.0" prefHeight="26.0" prefWidth="296.0" text="-" />
</children>
</AnchorPane>
<AnchorPane layoutX="7.0" layoutY="417.0" prefHeight="271.0" prefWidth="363.0" style="-fx-background-color: #F5F5F5;">
<effect>
<DropShadow />
</effect>
<children>
<BarChart fx:id="barChart" prefHeight="271.0" prefWidth="363.0" title="Gráfico Movimento">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</BarChart>
</children>
</AnchorPane>
<AnchorPane layoutX="379.0" layoutY="153.0" prefHeight="535.0" prefWidth="975.0" style="-fx-background-color: #F5F5F5;">
<effect>
<DropShadow />
</effect>
<children>
<LineChart fx:id="lineChart" layoutX="-2.0" prefHeight="535.0" prefWidth="968.0">
<xAxis>
<CategoryAxis side="BOTTOM" fx:id="xAxis" />
</xAxis>
<yAxis>
<NumberAxis fx:id="yAxis" side="LEFT" />
</yAxis>
</LineChart>
</children>
</AnchorPane>
<AnchorPane layoutX="379.0" layoutY="14.0" prefHeight="131.0" prefWidth="975.0" style="-fx-background-color: #F5F5F5;">
<effect>
<DropShadow />
</effect>
<children>
<TableView prefHeight="131.0" prefWidth="975.0">
<columns>
<TableColumn prefWidth="62.0" text="Janeiro" />
<TableColumn prefWidth="72.0" text="Fevereiro" />
<TableColumn prefWidth="79.0" text="Março" />
<TableColumn prefWidth="79.0" text="Abril" />
<TableColumn prefWidth="76.0" text="Maio" />
<TableColumn prefWidth="87.0" text="Junho" />
<TableColumn prefWidth="89.0" text="Julho" />
<TableColumn prefWidth="87.0" text="Agosto" />
<TableColumn prefWidth="83.0" text="Setembro" />
<TableColumn minWidth="0.0" prefWidth="81.0" text="Outubro" />
<TableColumn minWidth="0.0" prefWidth="79.0" text="Novembro" />
<TableColumn prefWidth="115.0" text="Dezembro" />
</columns>
</TableView>
</children>
</AnchorPane>
</children>
</AnchorPane>
FXMLGraficosController class
package graficos;
import Utilitarios.ConexaoBD;
import java.net.URL;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.ResourceBundle;
import java.util.stream.Stream;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javax.swing.JOptionPane;
public class FXMLGraficosController implements Initializable {
#FXML private DatePicker dtpInicial;
#FXML private DatePicker dtpFinal;
#FXML private Button btnOK;
#FXML private PieChart pieChart;
#FXML private BarChart<String, Double> barChart;
#FXML private LineChart<String, Number> lineChart;
#FXML private Label lblData;
ObservableList<PieChart.Data> pieChartData;
ObservableList<PieChart.Data> lineChartData;
//ArrayList<Integer> cell = new ArrayList<Integer>();
//ArrayList<String> name = new ArrayList<String>();
ConexaoBD connBD;
#Override
public void initialize(URL url, ResourceBundle rb) {
connBD = new ConexaoBD();
dtpInicial.setValue(LocalDate.now());
dtpFinal.setValue(LocalDate.now());
}
public void verificaData(javafx.event.ActionEvent event){
//String sData = dtpInicial.getValue().format(DateTimeFormatter.ofPattern("yyyy-mm-dd"));
java.sql.Date dDataIni = java.sql.Date.valueOf(dtpInicial.getValue());
java.sql.Date dDataFim = java.sql.Date.valueOf(dtpFinal.getValue());
String sDataIni = formataDataStr(dDataIni,1);
String sDataFim = formataDataStr(dDataFim,1);
lblData.setText("Período : " + sDataIni + " à " + sDataFim);
graficoPizza(sDataIni, sDataFim);
graficoLinhas(sDataIni, sDataFim);
}
public void graficoPizza(String sDataIni, String sDataFim){
String strSQL = null;
strSQL = " SELECT 'Boleto' AS Doacao, 'Valor' = COUNT(*)" +
" FROM BOLETO B " +
" WHERE B.BOLDATAVEN BETWEEN '"+sDataIni+"' AND '"+sDataFim+"' ";
strSQL = strSQL + " UNION ALL";
strSQL = strSQL + " SELECT 'Recibo' AS Doacao, 'Valor' = COUNT(*)" +
" FROM RECIBO R " +
" WHERE R.RECDATAVEN BETWEEN '"+sDataIni+"' AND '"+sDataFim+"' ";
strSQL = strSQL + " UNION ALL";
strSQL = strSQL + " SELECT 'Debito' AS Doacao, 'Valor' = COUNT(*)" +
" FROM DEBITO D " +
" WHERE D.DEBDATAVEN BETWEEN '"+sDataIni+"' AND '"+sDataFim+"' ";
pieChartData = FXCollections.observableArrayList();
try {
connBD.conectaBD();
} catch (ClassNotFoundException ex) {
JOptionPane.showMessageDialog(null, "Erro ao Conectar Banco de Dados - ERRO :" + ex.getMessage());
}
try {
connBD.executaSQL(strSQL); //Conecta no Banco conforme Parametro passado
if (connBD.rs.isBeforeFirst()){
while (connBD.rs.next()){
pieChartData.add(new PieChart.Data(connBD.rs.getString("Doacao"), connBD.rs.getInt("Valor")));
//name.add(connBD.rs.getString("Doacao"));
//cell.add(connBD.rs.getInt("Valor"));
System.out.println(connBD.rs.getString("Doacao") + " - " +connBD.rs.getString("Valor"));
}
}
pieChart.setData(pieChartData);
connBD.desconectaBD();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Erro ao Carregar Dados para Alteração!\n" + ex.getMessage());
}
}
public void graficoLinhas(String sDataIni, String sDataFim){
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Meses");
yAxis.setLabel("Valores");
lineChart.getData().clear();
ArrayList arrayAno = new ArrayList();
String sSQL = null;
sSQL = montaStrSQL(sDataIni, sDataFim);
try {
connBD.conectaBD();
} catch (ClassNotFoundException ex) {
JOptionPane.showMessageDialog(null, "Erro ao Conectar Banco de Dados - ERRO :" + ex.getMessage());
}
try {
connBD.executaSQL(sSQL); //Conecta no Banco conforme Parametro passado
if (connBD.rs.isBeforeFirst()){
try {
connBD.rs.beforeFirst();
while (connBD.rs.next()){
if(!arrayAno.contains(connBD.rs.getString("Ano"))){
arrayAno.add(connBD.rs.getString("Ano"));
System.out.println(connBD.rs.getString("Ano"));
}
}
connBD.rs.beforeFirst();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Erro ao Carregar Dados para Alteração!\n" + ex.getMessage());
}
XYChart.Series<String, Number>[] seriesArray = Stream.<XYChart.Series<String, Number>>generate(XYChart.Series::new).limit(arrayAno.size()).toArray(XYChart.Series[]::new);
for (int i = 0; i < arrayAno.size(); i++) {
try {
while (connBD.rs.next() && connBD.rs.getString("Ano").equals(arrayAno.get(i).toString())){
seriesArray[i].getData().add(new XYChart.Data(retornaMes(connBD.rs.getInt("Mes")), connBD.rs.getInt("Qtde")));
System.out.println(connBD.rs.getString("Ano") + " - " + connBD.rs.getString("Mes") + " - " + connBD.rs.getString("Qtde"));
}
seriesArray[i].setName("Ano: " + arrayAno.get(i).toString());
lineChart.getData().add(seriesArray[i]);
if (!connBD.rs.isLast())
connBD.rs.previous();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Erro ao Carregar Dados para Alteração!\n" + ex.getMessage());
}
}
}
connBD.desconectaBD();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Erro ao Carregar Dados para Alteração!\n" + ex.getMessage());
}
}
private String montaStrSQL(String sDataI, String sDataF){
String strSQL = null;
strSQL = "SELECT ANO, MES, SUM(QTDE) AS QTDE FROM (";
strSQL = strSQL + " SELECT 'Ano' = YEAR(B.BOLDATAVEN), 'Mes' = MONTH(B.BOLDATAVEN), 'Qtde' = COUNT(*)" +
" FROM BOLETO B " +
" WHERE B.BOLDATAVEN BETWEEN '"+sDataI+"' AND '"+sDataF+"' ";
strSQL = strSQL + " GROUP BY YEAR(B.BOLDATAVEN), MONTH(B.BOLDATAVEN)";
strSQL = strSQL + " UNION ALL";
strSQL = strSQL + " SELECT 'Ano' = YEAR(R.RECDATAVEN), 'Mes' = MONTH(R.RECDATAVEN), 'Qtde' = COUNT(*)" +
" FROM RECIBO R " +
" WHERE R.RECDATAVEN BETWEEN '"+sDataI+"' AND '"+sDataF+"' ";
strSQL = strSQL + " GROUP BY YEAR(R.RECDATAVEN), MONTH(R.RECDATAVEN)";
strSQL = strSQL + " UNION ALL";
strSQL = strSQL + " SELECT 'Ano' = YEAR(D.DEBDATAVEN), 'Mes' = MONTH(D.DEBDATAVEN), 'Qtde' = COUNT(*)" +
" FROM DEBITO D " +
" WHERE D.DEBDATAVEN BETWEEN '"+sDataI+"' AND '"+sDataF+"' ";
strSQL = strSQL + " GROUP BY YEAR(D.DEBDATAVEN), MONTH(D.DEBDATAVEN)";
strSQL = strSQL + ")Resultado";
strSQL = strSQL + " GROUP BY Resultado.ANO, Resultado.MES" ;
strSQL = strSQL + " ORDER BY Resultado.ANO, Resultado.MES" ;
return strSQL;
}
private String retornaMes(int iMes){
String sMes = null;
if (iMes == 1) sMes = "Jan";
else if (iMes == 2) sMes = "Fev";
else if (iMes == 3) sMes = "Mar";
else if (iMes == 4) sMes = "Abr";
else if (iMes == 5) sMes = "Mai";
else if (iMes == 6) sMes = "Jun";
else if (iMes == 7) sMes = "Jul";
else if (iMes == 8) sMes = "Ago";
else if (iMes == 9) sMes = "Set";
else if (iMes == 10) sMes = "Out";
else if (iMes == 11) sMes = "Nov";
else if (iMes == 12) sMes = "Dez";
return sMes;
}
public String formataDataStr(Date dData, int iOpc){
if (dData != null){
//JOptionPane.showMessageDialog(null, "Validando Data...");
SimpleDateFormat sdf;
switch (iOpc) {
case 1:
sdf = new SimpleDateFormat("yyyy-MM-dd");
break;
case 2:
sdf = new SimpleDateFormat("dd-MM-yyyy");
break;
default:
sdf = new SimpleDateFormat("dd/MM/yyyy");
break;
}
String sDataFormat = sdf.format(dData);
return sDataFormat;
} else {
//JOptionPane.showMessageDialog(null, "Retorno data vazio...");
return "";
}
}
}
BD class
package Utilitarios;
import java.sql.*;
import javax.swing.JOptionPane;
public class ConexaoBD {
public Connection conn = null;
public Statement stm = null;
public ResultSet rs = null;
private final String driverDB = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; //Nome do Driver conforme o BD a ser utilizado
private final String strDB = "jdbc:sqlserver://"; //String para montar Url Banco
private final String strIP = "XXX.X.XX.XX"; //IP do Servidor
private final String portaDB = ":1433;"; //Porta para montar Url Banco
private String nomeDB = "yourBD"; /Nome do Banco de Dados
private String usuarioDB = "youUSer"; //**
private String senhaDB = "yourPassword"; //**
private String connectionUrl = null;
public void conectaBD() throws ClassNotFoundException{ //Inicia Construtor
try {
try {
Class.forName(driverDB);
connectionUrl = strDB + strIP + portaDB + "databaseName=" + nomeDB + ";user=" + usuarioDB + ";password=" + senhaDB;
conn = DriverManager.getConnection(connectionUrl);
stm = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Erro ao Carregar Arquivo Configurações BD (ConexaoBD: conectaBD()):\n"+ex.getMessage());
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Erro Conexão BD - IP:\n"+ex.getMessage());
}
}
public void desconectaBD(){
try {
conn.close();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Erro ao Desconectar Banco de Dados (ConexaoBD: desconectaBD())\n"+ex.getMessage());
}
}
public void executaSQL(String strSQL){
try {
rs = stm.executeQuery(strSQL);
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Erro na Execução SQL (ConexaoBD: executaSQL())\n Erro: "+ex.getMessage() );
}
}
}
And the print of the execution ... now I can continue with the part of filling in the tablewiews, etc ...
Thank you all!
I have a webview and a label inside one of my xaml page. I am loading a local html file to the webview inside OnAppearing(). Problem is I cannot see the label. Webview takes whole screen. I tested in Android.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Test.Views.MyWebView">
<ContentPage.Content>
<StackLayout BackgroundColor="Red" VerticalOptions="FillAndExpand" Orientation="Vertical">
<Label HeightRequest="100" TextColor="Black" Text="Sample"/>
<StackLayout>
<ScrollView>
<other:HybridWebView x:Name="hybridWebView" VerticalOptions="FillAndExpand"
Navigating="webView_Navigating" HeightRequest="400" Navigated="MywebView_Navigated" />
</ScrollView>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Code behind
OnAppearing
protected override void OnAppearing()
{
base.OnAppearing();
NavigationPage.SetHasNavigationBar(this, false);
if (isFirstRun)
{
jsonOutput = JsonConvert.SerializeObject(payData);
//var htmlSource = new HtmlWebViewSource();
var urlSource = new UrlWebViewSource();
string url = DependencyService.Get<IBaseUrl>().Get();
TempUrl = Path.Combine(url, "xamarinhtmlmotor.html");
urlSource.Url = TempUrl;
hybridWebView.Source = urlSource;
isFirstRun = false;
Content = hybridWebView;
}
}
webView_Navigating
private void webView_Navigating(object sender, WebNavigatingEventArgs e)
{
UserDialogs.Instance.ShowLoading("Loading...", MaskType.Black);
}
Here I am currently checking for the android devices
MywebView_Navigated
private async void MywebView_Navigated(object sender, WebNavigatedEventArgs e)
{
UserDialogs.Instance.HideLoading();
if (Device.RuntimePlatform == Device.Android)
{
if (e.Url.Equals("file:///android_asset/web/xamarinhtmlmotor.html"))
{
getResult();
}
else if (e.Url.Equals("http://localhost/receipt_motor.aspx"))
{
string rtNo = "receiptNo";
string cvNo = "<%= hdntxtbxTaksit.ClientID %>";
receiptNo = await hybridWebView.EvaluateJavaScriptAsync($"document.getElementById('{rtNo}').value;");
cvNoteNo = await hybridWebView.EvaluateJavaScriptAsync($"document.getElementById('{cvNo}');");
if (receiptNo != null && !receiptNo.Equals(""))
{
}
if (cvNoteNo != null && !cvNoteNo.Equals(""))
{
}
}
}
}
}
Why don't you try with grid?
<Grid RowSpacing="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="Sample" FontSize="Large" HorizontalOptions="CenterAndExpand"></Label>
<StackLayout Grid.Row="1" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<other:HybridWebView x:Name="hybridWebView" VerticalOptions="FillAndExpand"
Navigating="webView_Navigating" Navigated="MywebView_Navigated" />
</StackLayout>
</Grid>
I am trying to create a sales app using Xamarin forms but am stuck on adding products to cart. I am using BindableLayout ItemsSource to populate my list horizontally:
<StackLayout BindableLayout.ItemsSource="{Binding NafakaList}" Orientation="Horizontal" Spacing="20"
VerticalOptions="Start">
<BindableLayout.ItemTemplate>
<DataTemplate x:Name="nafakaStackLayout">
<StackLayout VerticalOptions="Start">
<Frame Padding="0" HasShadow="False" HorizontalOptions="Start" VerticalOptions="Start"
CornerRadius="10" HeightRequest="150" WidthRequest="150">
<Image Source="{Binding Image}" Aspect="Fill" HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
</Frame>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<StackLayout>
<Label Text="{Binding Name}" TextColor="Black" FontSize="15" x:Name="nameView" />
<Label Text="{Binding Price}" x:Name="Price" Margin="0,-7,0,0" TextColor="#62153B"
FontSize="12" FontFamily="{StaticResource BoldFont}" />
</StackLayout>
<StackLayout Orientation="Horizontal" Margin="0" VerticalOptions="EndAndExpand">
<!--this is the button that I am using to pass data through-->
<Button Command="{Binding .}" BackgroundColor="White" CommandParameter="{Binding Product}"
HeightRequest="35" FontSize="Small" Text="Add to Cart" x:Name="cartAdd"
Clicked="cartAdd_Clicked" />
</StackLayout>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
This is my list and button click event:
public void cartAdd_Clicked(object sender, EventArgs e)
{
Object commandParameter = ((Button) sender).CommandParameter;
pr = (Product) NafakaList.GetItem(1);
DisplayAlert(pr.Name, "test", "Ok");
}
List:
public List<Product> NafakaList { get => GetProduct(); }
private List<Product> GetProduct(string name)
{
var products = new List<Product>();
products.Add(new Product {ID= 1, Image = "https://images.unsplash.com/photo-1568347355280-d33fdf77d42a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=752&q=80", Name = "Mchele", Price = "2500 tsh" });
products.Add(new Product { ID = 2, Image = "https://images.unsplash.com/photo-1574323347407-f5e1ad6d020b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=680&q=80", Name = "Ngano", Price = "1600 tsh" }); ;
products.Add(new Product { ID = 3, Image = "https://images.unsplash.com/photo-1579705745811-a32bef7856a3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80", Name = "Maharage", Price = "1500 tsh" });
products.Add(new Product { ID = 4, Image = "https://images.unsplash.com/photo-1560705185-d0291220a442?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=667&q=80", Name = "Kunde", Price = "1000 tsh" });
return products;
}
Try This Code also
public void cartAdd_Clicked(object sender, EventArgs e)
{
var item = sender as Button;
var data = item.BindingContext as Product;
...
}
You don't need to bind Command or CommandParameter in your code:
<Button Clicked="cartAdd_Clicked" ... />
Use the BindingContext to get the Product:
public void cartAdd_Clicked(object sender, EventArgs e)
{
var product = (Product)((Button)sender).BindingContext;
...
}
I have the main application class that does the following just fine:
#Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource(
"RecordScreen.fxml"));
Parent root = (Parent) loader.load();
Scene newScene = new Scene(root);
Stage newStage = new Stage();
newStage.setScene(newScene);
newStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
It launches a table view that displays people. I select a person, hit the edit button, and try to launch a window that will let me edit them.
#FXML
public void editPerson() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource(
"PersonEditor.fxml"));
PersonEditorCtrl ctrl = loader.getController();
ctrl.init(table.getSelectionModel().getSelectedItem());
Parent root = (Parent) loader.load();
Scene newScene = new Scene(root);
Stage newStage = new Stage();
newStage.setScene(newScene);
newStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
The problem is, getController is returning null. I have been following this pattern for the past 2 weeks with no problems whatsoever. What am I doing wrong now? These untraceable bugs are aggravating!!!
Here are my two fxmls:
The screen with tableview:
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="application.RecordsCtrl">
<!-- TODO Add Nodes -->
<children>
<VBox id="VBox" alignment="CENTER" spacing="0.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<TableView fx:id="table" prefHeight="-1.0" prefWidth="-1.0">
<columns>
<TableColumn prefWidth="75.0" text="Name" fx:id="nameCol" />
<TableColumn prefWidth="75.0" text="Age" fx:id="ageCol" />
</columns>
</TableView>
<Button mnemonicParsing="false" onAction="#editPerson" text="Edit" />
</children>
</VBox>
</children>
</AnchorPane>
The person editor:
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="application.PersonEditorCtrl">
<!-- TODO Add Nodes -->
<children>
<VBox layoutX="0.0" layoutY="0.0" prefHeight="-1.0" prefWidth="-1.0">
<children>
<TextField fx:id="nameField" prefWidth="200.0" />
<TextField fx:id="ageField" prefWidth="200.0" />
<Button mnemonicParsing="false" text="Button" />
</children>
</VBox>
</children>
</AnchorPane>
Change this
#FXML
public void editPerson() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource(
"PersonEditor.fxml"));
PersonEditorCtrl ctrl = loader.getController();
ctrl.init(table.getSelectionModel().getSelectedItem());
Parent root = (Parent) loader.load();
Scene newScene = new Scene(root);
Stage newStage = new Stage();
newStage.setScene(newScene);
newStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
To that:
#FXML
public void editPerson() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource(
"PersonEditor.fxml"));
Parent root = (Parent) loader.load();
PersonEditorCtrl ctrl = loader.getController();
ctrl.init(table.getSelectionModel().getSelectedItem());
Scene newScene = new Scene(root);
Stage newStage = new Stage();
newStage.setScene(newScene);
newStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
You first have to run loader.load() then you can get the Controller.
Patrick