I would like to know why My chart doesn't get new settings after my set ups, is not update the axis.
Main class:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 1200, 800));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller class ; after Apply button click u can set the variables which u want have on Axis X and Y, also using some validations,
package sample;
import javafx.beans.binding.Bindings;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.geometry.Side;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.control.TextField;
public class Controller {
#FXML
private TextField xMin, xMax, yMin, yMax, xTick, yTick, width, height;
#FXML
private LineChart<Number, Number> axesTest;
#FXML
private NumberAxis xAxis, yAxis;
private Axes axes;
public void applyButtonClicked(ActionEvent event) {
System.out.println("Applyed...");
axes = new Axes();
axes.setxMin(Double.parseDouble(xMin.getText()));
axes.setxMax(Double.parseDouble(xMax.getText()));
axes.setyMin(Double.parseDouble(yMin.getText()));
axes.setyMax(Double.parseDouble(yMax.getText()));
axes.setxTickUnit(Double.parseDouble(xTick.getText()));
axes.setyTickUnit(Double.parseDouble(yTick.getText()));
axes.setAxesWidth(Integer.parseInt(width.getText()));
axes.setAxesHeight(Integer.parseInt(height.getText()));
xAxis = new NumberAxis(axes.getxMin(), axes.getxMax(), axes.getxTickUnit());
xAxis.setSide(Side.BOTTOM);
xAxis.setMinorTickVisible(false);
xAxis.setPrefWidth(axes.getAxesWidth());
xAxis.setLayoutY(axes.getAxesHeight()/2);
xAxis.autosize();
xAxis.setLowerBound(axes.getxMin());
xAxis.setUpperBound(axes.getxMax());
xAxis.setTickUnit(axes.getxTickUnit());
yAxis = new NumberAxis(axes.getyMin(), axes.getyMax(), axes.getyTickUnit());
yAxis.setSide(Side.LEFT);
yAxis.setMinorTickVisible(false);
yAxis.setPrefHeight(axes.getAxesHeight());
yAxis.layoutXProperty().bind(Bindings.subtract((axes.getAxesWidth() / 2) + 1, yAxis.widthProperty()));
yAxis.setLowerBound(axes.getyMin());
yAxis.setUpperBound(axes.getyMax());
yAxis.setTickUnit(axes.getyTickUnit());
axesTest = new LineChart<Number, Number>(xAxis, yAxis);
// System.out.println("xMin : " + axes.getxMin() + "xMax : " + axes.getxMax() + "yMin :" + axes.getyMin() + "yMax : " + axes.getyMax()
// + "xTick : " + axes.getxTickUnit() + "yTick : " + axes.getyTickUnit());
}
public void startButtonClicked() {
}
}
Axes class Is for setting every variable which i want to have on my Axes.
package sample;
import javafx.scene.chart.NumberAxis;
import javafx.scene.layout.Pane;
public class Axes extends Pane {
private NumberAxis xAxis;
private NumberAxis yAxis;
private double xMin, xMax, yMin, yMax, xTickUnit, yTickUnit;
private int axesWidth, axesHeight;
public Axes() {
this.xMin = 0;
this.xMax = 0;
this.yMin = 0;
this.yMax = 0;
this.xTickUnit = 0;
this.yTickUnit = 0;
this.axesWidth = 0;
this.axesHeight = 0;
}
public NumberAxis getXAxis() {
return xAxis;
}
public NumberAxis getYAxis() {
return yAxis;
}
public int getAxesWidth() {
return axesWidth;
}
public void setAxesWidth(int axesWidth) {
this.axesWidth = axesWidth;
}
public int getAxesHeight() {
return axesHeight;
}
public void setAxesHeight(int axesHeight) {
this.axesHeight = axesHeight;
}
public double getxMin() {
return xMin;
}
public void setxMin(double xMin) {
this.xMin = xMin;
}
public double getxMax() {
return xMax;
}
public void setxMax(double xMax) {
this.xMax = xMax;
}
public double getyMin() {
return yMin;
}
public void setyMin(double yMin) {
this.yMin = yMin;
}
public double getyMax() {
return yMax;
}
public void setyMax(double yMax) {
this.yMax = yMax;
}
public double getxTickUnit() {
return xTickUnit;
}
public void setxTickUnit(double xTickUnit) {
this.xTickUnit = xTickUnit;
}
public double getyTickUnit() {
return yTickUnit;
}
public void setyTickUnit(double yTickUnit) {
this.yTickUnit = yTickUnit;
}
}
sample.fxml file, every thing i created in the scene builder.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="borderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<top>
<Label text="JavaFX Simulation" BorderPane.alignment="CENTER">
<font>
<Font name="Calibri" size="15.0" />
</font>
</Label>
</top>
<bottom>
<Label text="\#Copyright by XXX" BorderPane.alignment="CENTER" />
</bottom>
<left>
<VBox prefHeight="345.0" prefWidth="192.0" spacing="10.0" BorderPane.alignment="CENTER">
<children>
<GridPane hgap="10.0" vgap="10.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextField promptText="xMin" fx:id="xMin" />
<TextField promptText="xMax" GridPane.columnIndex="1" fx:id="xMax" />
<TextField fx:id="yMin" promptText="yMin" GridPane.rowIndex="1" />
<TextField fx:id="yMax" promptText="yMax" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="width" promptText="width" GridPane.rowIndex="3" />
<TextField fx:id="height" promptText="height" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<TextField promptText="xTick" GridPane.rowIndex="2" fx:id="xTick" />
<TextField fx:id="yTick" promptText="yTick" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<HBox prefHeight="100.0" prefWidth="200.0" GridPane.rowIndex="4">
<children>
<Button mnemonicParsing="false" onAction="#applyButtonClicked" text="Apply" />
</children>
</HBox>
<Button mnemonicParsing="false" onAction="#startButtonClicked" text="Start" GridPane.rowIndex="5" />
<Button mnemonicParsing="false" text="Restart" GridPane.columnIndex="1" GridPane.rowIndex="5" />
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</GridPane>
</children>
<BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</BorderPane.margin>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</VBox>
</left>
<center>
<LineChart fx:id="axesTest" BorderPane.alignment="CENTER">
<xAxis>
<NumberAxis lowerBound="-10.0" side="BOTTOM" fx:id="xAxis" />
</xAxis>
<yAxis>
<NumberAxis fx:id="yAxis" lowerBound="-10.0" side="LEFT" />
</yAxis>
</LineChart>
</center>
</BorderPane>
At the center of the Border Pane should be for the start application default Axis and after clicking the Apply button should showed the Axis which I want to. It doesn't update it, so my question is : What I am doing wrong ? Or what I am missing in the code ? Thanks.
The first problem you have is that you are adding new instances of NumberAxis and LineChart every time you click on the apply button. Those instances are not added to the scene graph, and the one you already have (those annotated with #FXML and created by the FXMLLoader), don't get any notifications.
So you have to remove this:
public void applyButtonClicked(ActionEvent event) {
xAxis = new NumberAxis(axes.getxMin(), axes.getxMax(), axes.getxTickUnit());
yAxis = new NumberAxis(axes.getyMin(), axes.getyMax(), axes.getyTickUnit());
axesTest = new LineChart<Number, Number>(xAxis, yAxis);
}
and just set:
public void applyButtonClicked(ActionEvent event) {
//xAxis = new NumberAxis(axes.getxMin(), axes.getxMax(), axes.getxTickUnit());
xAxis.setLowerBound(axes.getxMin());
xAxis.setUpperBound(axes.getxMax());
xAxis.setTickUnit(axes.getxTickUnit());
//yAxis = new NumberAxis(axes.getyMin(), axes.getyMax(), axes.getyTickUnit());
yAxis.setLowerBound(axes.getyMin());
yAxis.setUpperBound(axes.getyMax());
yAxis.setTickUnit(axes.getyTickUnit());
//axesTest = new LineChart<Number, Number>(xAxis, yAxis);
}
The second problem: by default the axes have auto ranging enabled, so any change applied will be overridden.
So just disable it:
public void initialize() {
axes = new Axes();
xAxis.setAutoRanging(false);
yAxis.setAutoRanging(false);
}
And finally, you can't bind the layoutX property, since it's already bound. Instead use the translateX property:
yAxis.translateXProperty().bind(Bindings.subtract((axes.getAxesWidth() / 2) + 1, yAxis.widthProperty()));
Related
I am trying to create a hamburger menu in xaml, but zero success. I was trying to use the samples provided [here][1], but zero success.
My idea is to create a view model that has a list of FlyoutItems then inject this view model to the AppShell.
public partial class ShellViewModel : ObservableObject
{
public List<FlyoutItem> FlyoutItems { get; private set; } = new List<FlyoutItem>();
public ShellViewModel()
{
AddMenuItems();
}
private void AddMenuItems()
{
var flyoutItems = new List<FlyoutItem>
{
new FlyoutItem
{
Title = "Item 1"
},
new FlyoutItem
{
Title = "Item 2"
}
};
FlyoutItems.AddRange(flyoutItems);
}
}
public partial class AppShell : Shell
{
private ShellViewModel viewModel => BindingContext as ShellViewModel;
public AppShell(ShellViewModel viewModel)
{
BindingContext = viewModel;
RegisterRoutes();
InitializeComponent();
}
private void RegisterRoutes()
{
Routing.RegisterRoute(PageRoutes.LoginPage, typeof(LoginPage));
Routing.RegisterRoute(PageRoutes.RegisterPage, typeof(RegisterPage));
Routing.RegisterRoute(PageRoutes.HomePage, typeof(MainPage));
Routing.RegisterRoute(PageRoutes.DetailsPage, typeof(PlayerDetailsPage));
Routing.RegisterRoute(PageRoutes.AddOrUpdatePage, typeof(AddOrUpdatePlayer));
}
}
In the XAML sometign like this
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MauiUI.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiUI"
xmlns:pages="clr-namespace:MauiUI.Pages">
<Shell.ItemTemplate>
<DataTemplate>
<CollectionView BindingContext="{x:Reference shell}"
IsGrouped="True"
ItemsSource="{Binding FlyoutItems}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Title}"
TextColor="White"
FontSize="18" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</DataTemplate>
</Shell.ItemTemplate>
<ShellContent
Title="Amazons of Volleyball"
ContentTemplate="{DataTemplate pages:SplashPage}"
Route="HomePage" />
</Shell>
thnx
[1]: https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/shell/flyout?view=net-maui-7.0
I am trying to create a hamburger menu in xaml, but zero success.
You can add this code in your AppShell.xaml:
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MauiUI.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiUI"
xmlns:views="clr-namespace:MauiUI.Pages">
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
<ShellContent Title="Home"
Route="home"
ContentTemplate="{DataTemplate local:MainPage}" />
<ShellContent Title="NewPage1"
ContentTemplate="{DataTemplate pages:NewPage1}" />
</FlyoutItem>
</Shell>
Or you can add this code in your AppShell.xaml.cs:
public partial class AppShell : Shell
{
public AppShell ()
{
InitializeComponent ();
FlyoutItem flyoutItem = new FlyoutItem ();
flyoutItem.FlyoutDisplayOptions = FlyoutDisplayOptions.AsMultipleItems;
flyoutItem.Items.Add (new ShellContent () { Title = "NewPage1", Content = new NewPage1 () });
flyoutItem.Items.Add (new ShellContent () { Title = "home", Content = new MainPage () });
myshell.Items.Add (flyoutItem);
}
}
I'm trying to make a windows-like navigation item.
This is the implementation:
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="NavItem.NavItem"
xmlns:local="clr-namespace:NavItem"
x:DataType="local:NavItem">
<Frame HeightRequest="50" CornerRadius="6" BackgroundColor="{StaticResource Tertiary}" BorderColor="{StaticResource Secondary}" Padding="10">
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</Frame.GestureRecognizers>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label x:Name="LblText" Text="{Binding Text}" Grid.Column="0" TextColor="{StaticResource White}" />
<Label Text=">" Grid.Column="1" TextColor="{StaticResource White}" FontSize="16" />
</Grid>
</Frame>
</ContentView>
public partial class NavItem : ContentView
{
string text;
public string Text
{
get => text;
set { text = value; OnPropertyChanged(); }
}
public string PageName { get; set; }
public NavItem()
{
InitializeComponent();
}
private async void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
await Shell.Current.GoToAsync(PageName);
}
}
<VerticalStackLayout>
<local:NavItem Text="Page 1" PageName="Page1" />
<local:NavItem Text="Page 2" PageName="Page2" />
</VerticalStackLayout>
The navigation is ok but the binding fails to set Text property of label LblText.
So this is the rendering:
EDIT: I also tried with a bindable attribute, same result
public string Text
{
get => (string)GetValue(TextProperty);
set { SetValue(TextProperty, value); OnPropertyChanged(); }
}
public static readonly BindableProperty TextProperty =
BindableProperty.Create(nameof(Text), typeof(string), typeof(NavItem), "", BindingMode.TwoWay);
I just had to set the binding context to itself:
public NavItem()
{
InitializeComponent();
BindingContext = this;
}
When i trying to navigate from login page to masterDetailpage, I am getting error says
"System.Reflection.TargetInvocationException
Message=Exception has been thrown by the target of an invocation."
I tried this in the login function when user successful logged in
async void Login()
{
try
{
var current = Connectivity.NetworkAccess;
if (current == NetworkAccess.Internet)
{
if (IsValidated)
{
await navigationRef.PushPopupAsync(new LoaderPage()).ConfigureAwait(false);
userDetails = await webServicesRepository.UserLogin(Phone, Password, "123113123", "Android").ConfigureAwait(false);
if (userDetails != null && userDetails.status == "200")
{
await navigationRef.PopPopupAsync().ConfigureAwait(false);
MasterDetailPage fpm = new MasterDetailPage
{
Master = new MainMenuPageMaster(),
Detail = new NavigationPage(new HomePage())
};
Application.Current.MainPage = fpm;
//Application.Current.MainPage = new NavigationPage(new MainMenuPage());
//await navigationRef.PushAsync(new MainMenuPage()).ConfigureAwait(false);
}
else
{
await navigationRef.PopPopupAsync().ConfigureAwait(false);
await Application.Current.MainPage.DisplayAlert(Constants.DISPLAY_POPUP_TITLE, Constants.NO_DATA_FOUND, Constants.DISPLAY_POPUP_BUTTON).ConfigureAwait(false);
}
}
else
{
await Application.Current.MainPage.DisplayAlert(Constants.DISPLAY_POPUP_TITLE, "You must fill all areas correctly!", Constants.DISPLAY_POPUP_BUTTON).ConfigureAwait(false);
}
}
else
{
await Application.Current.MainPage.DisplayAlert(Constants.DISPLAY_NETWORK_ERROR_TITLE, Constants.DISPLAY_NETWORK_ERROR_MESSAGE, Constants.DISPLAY_POPUP_BUTTON).ConfigureAwait(false);
}
}
catch(Exception ex)
{
Console.WriteLine(ex.InnerException.Message);
await Application.Current.MainPage.DisplayAlert(Constants.DISPLAY_POPUP_TITLE, Constants.NO_DATA_FOUND, Constants.DISPLAY_POPUP_BUTTON).ConfigureAwait(false);
}
}
MasterDetailPage :
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage 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="intSetSet.MainMenuPage"
xmlns:views="clr-namespace:XXXXXX"
NavigationPage.HasNavigationBar="False"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.UseSafeArea="true">
<MasterDetailPage.Master>
<views:MainMenuPageMaster x:Name="masterPage" Title="Menu" Icon="ListIcon.png" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<views:HomePage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
c#
public partial class MainMenuPage : MasterDetailPage
{
public MainMenuPage()
{
InitializeComponent();
try
{
masterPage.MenuItemsListView.ItemSelected += ListView_ItemSelected;
MessagingCenter.Subscribe<EventArgs>(this, "OpenMenu", args =>
{
IsPresented = !IsPresented;
});
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as MainMenuPageModel;
if (item == null)
return;
var page = (Page)Activator.CreateInstance(item.TargetType);
//var page = item.TargetType;
page.Title = item.Title;
Detail = new NavigationPage(page);
IsPresented = false;
masterPage.MenuItemsListView.SelectedItem = null;
}
}
ContentPage to generate List options:
<?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="XXXXX.MainMenuPageMaster"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.UseSafeArea="true">
<StackLayout>
<ListView x:Name="MenuItemsListView"
SeparatorVisibility="None"
x:FieldModifier="public"
HasUnevenRows="true"
ItemsSource="{Binding MenuItems}">
<ListView.Header>
<StackLayout BackgroundColor="#CEDAEE">
<StackLayout Orientation="Horizontal"
Padding="20">
<Image Margin="10,10,0,0"
Source="setsetlogo.png"
WidthRequest="80"
HeightRequest="80"
HorizontalOptions="Start"></Image>
<Label HorizontalOptions="StartAndExpand"
VerticalTextAlignment="Center"
Text="IntSetSet"
TextColor="White"
FontSize="24" />
</StackLayout>
<BoxView BackgroundColor="Teal"
HorizontalOptions="FillAndExpand"
HeightRequest="1"></BoxView>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout HorizontalOptions="FillAndExpand"
BackgroundColor="#CEDAEE">
<StackLayout Padding="10,10"
Orientation="Horizontal">
<Image Source="{Binding Icon}"
WidthRequest="40"
HeightRequest="40"
VerticalOptions="Center"
HorizontalOptions="Start"></Image>
<Label VerticalOptions="Center"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Start"
HorizontalOptions="StartAndExpand"
TextColor="White"
Text="{Binding Title}"
FontSize="Medium" />
</StackLayout>
<BoxView BackgroundColor="Teal"
HorizontalOptions="FillAndExpand"
HeightRequest="1"></BoxView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<StackLayout BackgroundColor="#CEDAEE" Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<Button Command="{Binding LogoutCommand}" Text="LogOut" BackgroundColor="#CEDAEE" TextColor="Yellow" HorizontalOptions="EndAndExpand">
</Button>
<!--<Button Clicked="LogoutButton_Clicked" Text="LogOut" BackgroundColor="#CEDAEE" TextColor="Yellow" HorizontalOptions="EndAndExpand">
</Button>-->
</StackLayout>
</ListView.Footer>
</ListView>
</StackLayout>
</ContentPage>
C#
public partial class MainMenuPageMaster : ContentPage
{
public MainMenuPageMaster()
{
InitializeComponent();
BindingContext = new MainMenuPageViewModel();
}
}
View Model:
public class MainMenuPageViewModel : INotifyPropertyChanged
{
public ObservableCollection<MainMenuPageModel> MenuItems { get; set; }
public ICommand LogoutCommand { get; }
public MainMenuPageViewModel()
{
try
{
MenuItems = new ObservableCollection<MainMenuPageModel>(new[]
{
new MainMenuPageModel { Id = 0, Title = "Home", Icon="shop.png", TargetType= typeof(HomePage) },
new MainMenuPageModel { Id = 1, Title = "Profile", Icon="shop.png", TargetType= typeof(ProfilePage) },
new MainMenuPageModel { Id = 2, Title = "Referral History", Icon="paper_money.png", TargetType= typeof(ReferralHistoryPage) },
});
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged == null)
return;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
I want to Navigate from the login page to master details page on successful login
I would like to do such table with editing like here -> http://showcase.richfaces.org/richfaces/component-sample.jsf?demo=dataTable&sample=dataTableEdit&skin=blueSky . The problem ist that, when I do changes in editPane (popupPanel) they are not remembered in private OsobaTelefon edytujOsobe. This make update impossible via JPA. I have all getters and setters and class OsobaTelefon implements Serializable.
#ManagedBean(name = "administrator")
#ViewScoped
#SessionScoped
public class Administrator implements Serializable
#EJB
private UzytkownikFacade uzytkownikFacade;
private static final long serialVersionUID = 1L;
#EJB
private OsobaFacade osobaFacade;
private Osoba osobaAdmina;
private int numerStrony = 1;
private Uzytkownik uzytkownik;
private List<Osoba> listaOsob;
private static final int CLIENT_ROWS_IN_AJAX_MODE = 10;
private int clientRows;
private int wybranaOsoba;
private OsobaTelefon edytujOsobe; //it doesn't remember the changes made in editPane
private List<OsobaTelefon> osobyITelefony;
/**
* Creates a new instance of Administrator
*/
public Administrator() {
}
public void aktualizacjaWybranejOsoby() {
this.osobyITelefony.set(this.wybranaOsoba, this.edytujOsobe);
Osoba nowaOsoba = new Osoba();
List<Telefon> nowaListaTelefonow = new ArrayList<Telefon>();
OsobaTelefon osobaTelefon = this.osobyITelefony.get(this.wybranaOsoba);
int o = this.osobyITelefony.get(this.wybranaOsoba).getIdosoby();
int of = this.osobyITelefony.get(this.wybranaOsoba).getIdtelefonu();
System.out.println("Wybrana osoba ID " + o);
System.out.println("Wybrane ID fona " + of);
boolean znalezionoOsobe = false;
Iterator<Osoba> iteOs = this.listaOsob.iterator();
while (!znalezionoOsobe && iteOs.hasNext()) {
Osoba os = iteOs.next();
if (os.getIdosoba() == o) {
znalezionoOsobe = true;
nowaOsoba.setIdosoba(os.getIdosoba());
nowaOsoba.setImie(osobaTelefon.getImie());
nowaOsoba.setNazwisko(osobaTelefon.getNazwisko());
nowaOsoba.setKodpocztowy(osobaTelefon.getKodpocztowy());
nowaOsoba.setMiejscowosc(osobaTelefon.getMiejscowosc());
nowaOsoba.setUlica(osobaTelefon.getUlica());
nowaOsoba.setUzytkownikList(os.getUzytkownikList());
Telefon nowyTelefon = new Telefon();
for (Telefon tel : os.getTelefonList()) {
if (tel.getIdtelefon() == of) {
nowyTelefon.setFkIdosoba(nowaOsoba);
nowyTelefon.setIdtelefon(of);
nowyTelefon.setNumer(this.edytujOsobe.getNumer());
System.out.println("Nr tel. "+tel.getNumer());
nowyTelefon.setOpis(this.edytujOsobe.getOpis());
nowyTelefon.setZastrzezony(this.edytujOsobe.getZastrzezony());
nowaListaTelefonow.add(nowyTelefon);
} else {
nowaListaTelefonow.add(tel);
}
}
nowaOsoba.setTelefonList(nowaListaTelefonow);
this.osobaFacade.aktualizujOsoba(nowaOsoba);
this.pobierzOsobyDoTabeli();
}
}
}
public List<Osoba> pobierzOsobyDoTabeli() {
//getting people with phone to List<OsobaTelefon> works good
}
public void switchAjaxLoading(ValueChangeEvent event) {
this.clientRows = (Boolean) event.getNewValue() ? CLIENT_ROWS_IN_AJAX_MODE : 0;
}
public void zapelnijListeTelefonow() {
//getting people phone number to List<Phone> works good
}
public void usunOsobe() {
//deleting people works good
}
}
The XHTML
<a4j:status onstart="#{rich:component('statPane')}.show()" onstop="#{rich:component('statPane')}.hide()" />
<h:form id="formProjekty">
<rich:dataTable value="#{administrator.osobyITelefony}"
var="pr"
iterationStatusVar="ite"
id="table"
rows="8" >
<rich:column width="auto">
<f:facet name="header">Imię</f:facet>
<h:outputText value="#{pr.imie}" />
</rich:column>
<rich:column>
<a4j:commandLink styleClass="no-decor"
render="editGrid"
execute="#this"
oncomplete="#{rich:component('editPane')}.show()">
<h:graphicImage library="img" name="edit.gif" alt="Edycja"/>
<a4j:param value="#{ite.index}"
assignTo="#{administrator.wybranaOsoba}" />
<f:setPropertyActionListener target="#{administrator.edytujOsobe}"
value="#{pr}" />
</a4j:commandLink>
<a4j:commandLink styleClass="no-decor"
execute="#this"
render="#none"
oncomplete="#{rich:component('confirmPane')}.show()">
<h:graphicImage library="img" name="delete.gif" alt="Usuń"/>
<a4j:param value="#{ite.index}"
assignTo="#{administrator.wybranaOsoba}" />
<f:setPropertyActionListener target="#{administrator.edytujOsobe}"
value="#{pr}" />
</a4j:commandLink>
</rich:column>
<f:facet name="footer">
<rich:dataScroller page="#{administrator.numerStrony}" />
</f:facet>
</rich:dataTable>
<a4j:jsFunction name="remove"
action="#{administrator.usunOsobe()}"
render="table"
execute="#this"
oncomplete="#{rich:component('confirmPane')}.hide();" />
<a4j:jsFunction name="edycja"
action="#{administrator.aktualizacjaWybranejOsoby()}"
render="table"
execute="#this"
oncomplete="#{rich:component('editPane')}.hide();" />
<rich:popupPanel id="statPane" autosized="true">
<h:graphicImage library="img" name="ai.gif" alt="Czekaj"/>
Proszę czekać...
</rich:popupPanel>
<rich:popupPanel id="confirmPane" autosized="true">
Czy na pewno usunać?
<a4j:commandButton value="Tak" onclick="remove();
return false;" />
<a4j:commandButton value="Nie"
onclick="#{rich:component('confirmPane')}.hide();
return false;" />
</rich:popupPanel>
<rich:popupPanel header="Edycja Osoby"
id="editPane"
domElementAttachment="parent" width="180" height="420">
<h:panelGrid columns="1" id="editGrid">
<h:panelGroup >
<h:outputText value="Imię" /><br />
<h:inputText value="#{administrator.edytujOsobe.imie}" >
<f:validateLength maximum="32" minimum="3"/>
</h:inputText>
</h:panelGroup>
</h:panelGrid><br/>
<a4j:commandButton value="Aktualizuj"
onclick="edycja(); return false;"/>
<a4j:commandButton value="Anuluj"
onclick="#{rich:component('editPane')}.hide();
return false;" />
</rich:popupPanel>
</h:form>
if you can change it then make your Aktualizuj a4j-link a little bit easier. Just try that:
<a4j:commandButton value="Aktualizuj"
onclick="#{rich:component('editPane')}.hide();"
action="#{administrator.aktualizacjaWybranejOsoby()}" render="table"/>
and put an a4j:region about your inputText and your link to send only the required values:
<rich:popupPanel header="Edycja Osoby"
id="editPane"
domElementAttachment="parent" width="180" height="420">
<a4j:region>
<h:panelGrid columns="1" id="editGrid">
<h:panelGroup >
<h:outputText value="Imię" /><br />
<h:inputText value="#{administrator.edytujOsobe.imie}" >
<f:validateLength maximum="32" minimum="3"/>
</h:inputText>
</h:panelGroup>
</h:panelGrid><br/>
<a4j:commandButtonvalue="Aktualizuj" onclick="# {rich:component('editPane')}.hide();"action="#{administrator.aktualizacjaWybranejOsoby()}" render="table"/>
<a4j:commandButton value="Anuluj"
onclick="#{rich:component('editPane')}.hide();
return false;" />
</a4j:region>
</rich:popupPanel>
I also add a render="table" to the Aktualizuj a4j:link to update the value in the datatable
I have Employee Entity of northwind database and one of the field of this entity is "Photo" which is of type "Binary".
Now my question is how should i display the "Photo"fields in the Silverlight 4 datagrid so that i can view the employee photo?
What do i need todo in my WCF code or my ModelView Code?
My XAML code is given below:
<navigation:Page x:Class="NorthWind.SMS.UI.Views.EmployeeListing"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="EmployeeListing Page" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="50" MaxHeight="50" MinHeight="50" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Height="Auto" HorizontalAlignment="Left" Margin="5,5,0,0" Name="grid1" VerticalAlignment="Top" Width="Auto" />
<TextBlock Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="tbHeader" Text="Employee Listing" VerticalAlignment="Top" FontSize="14" FontFamily="Verdana" TextAlignment="Center" />
<sdk:DataGrid Grid.Row="1" ItemsSource="{Binding Path=Employees}" AutoGenerateColumns="False" Height="Auto" HorizontalAlignment="Left" Margin="5,5,0,0" Name="dgEmployee" VerticalAlignment="Top" Width="Auto" AlternatingRowBackground="{x:Null}">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Name">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding EmployeeName.TitleOfCourtesy}"></Run>
<Run Text="{Binding EmployeeName.FirstName}"></Run>
<Run Text="{Binding EmployeeName.LastName}"></Run></TextBlock>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTextColumn Binding="{Binding Path=Title}" Header="Title" />
<sdk:DataGridTextColumn Binding="{Binding Path=HireDate}" Header="HireDate" />
<sdk:DataGridTextColumn Binding="{Binding Path=BirthDate}" Header="DOB" />
<sdk:DataGridTextColumn Binding="{Binding Path=HomePhone}" Header="Phone" />
<sdk:DataGridTextColumn Binding="{Binding Path=City}" Header="City" />
<sdk:DataGridTextColumn Binding="{Binding Path=Region}" Header="Region" />
<sdk:DataGridTextColumn Binding="{Binding Path=Country}" Header="Country" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
</navigation:Page>
My ModelView Code is given below;
private void RefreshEmployees()
{
this.serviceClient.GetEmployeesListingCompleted += (s, e) =>
{
this.Employees = e.Result;
};
this.serviceClient.GetEmployeesListingAsync();
}
My WCF code that is getting the data is show below;
[OperationContract]
public IEnumerable<Employee> GetEmployeesListing()
{
using (var context = new NorthwindEntities())
{
//context.ContextOptions.LazyLoadingEnabled = false;
var result = context.Employees.ToList();
result.ForEach(e => context.Detach(e));
return result;
}
}
I found the answer to my question here is what i did;
Step 1:
WCF code modified to convert the Binary "Photo" field to Jpeg format.
Code is shown below;
[OperationContract]
public IEnumerable<Employee> GetEmployeesListing()
{
List<Employee> empList = new List<Employee>();
using (var context = new NorthwindEntities())
{
//context.ContextOptions.LazyLoadingEnabled = false;
var result = context.Employees.ToList();
result.ForEach(e => context.Detach(e));
//return result;
foreach (Employee emp in result)
{
Employee e = new Employee();
e.EmployeeName.TitleOfCourtesy = emp.EmployeeName.TitleOfCourtesy;
e.EmployeeName.FirstName = emp.EmployeeName.FirstName;
e.EmployeeName.LastName = emp.EmployeeName.LastName;
e.Title = emp.Title;
e.HireDate = emp.HireDate;
e.BirthDate = emp.BirthDate;
e.City = emp.City;
e.Region = emp.Region;
e.Country = emp.Country;
if (emp.Photo != null)
{
byte[] blob = emp.Photo;
using (MemoryStream ms = new MemoryStream())
{
ms.Write(blob, 78, blob.Length - 78);
Bitmap bm = (Bitmap)Image.FromStream(ms);
using (MemoryStream msJpg = new MemoryStream())
{
bm.Save(msJpg, ImageFormat.Jpeg);
e.Photo = msJpg.GetBuffer();
}
}
}
empList.Add(e);
}
return empList;
}
}
Step 2:
Create a Image Converter class implementing the IValueConverter interface in your Silverlight project.
Code is shown below;
public class ByteToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
byte[] pic = value as byte[];
if (value != null)
{
MemoryStream ms = new MemoryStream((byte[])value, false);
BitmapImage bmi = new BitmapImage();
bmi.SetSource(ms);
return bmi;
}
else return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Step 4
In the XAML file where you have your Data grid add a refernce of ByteToImageConverter class like this;
xmlns:src="clr-namespace:NorthWind.SMS.UI.Converters"
Step 5
Add a Static resource details in your XAML file like this;
<UserControl.Resources>
<src:ByteToImageConverter x:Key="ConvertToImage">
</src:ByteToImageConverter>
</UserControl.Resources>
Step 6
Update your datagrid image template like this;
<sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image x:Name="img1" Source ="{Binding Path=Photo, Converter={StaticResource ConvertToImage}}" Width="75" Height="75" Visibility="Visible"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
This solution is working just fine for me.