JavaFX can't show contextmenu in FXML Application - contextmenu

i'm beginning with JavaFX.
I'm testing to create a FXML project and trying to display a context menu when i click into a row of the tableview, but i canĀ“t see my context menu.
My code is:
package fxmltableview;
import java.net.URL;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ResourceBundle;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
/**
*
* #author aCedano
*/
public class FXMLTableViewController implements Initializable {
#FXML private TableView<Person> tableView;
#FXML private TableColumn<Person, String> firstNameColumn;
#FXML private TableColumn<Person, String> lastNameColumn;
#FXML private TableColumn<Person, String> testColumn;
#FXML private ContextMenu resultadoContextMenu;
Connection con;
private DBClass objDbClass;
private ObservableList<Person> data;
#Override
public void initialize(URL location, ResourceBundle resources) {
assert tableView != null : "fx:id=\"tableView\" was not injected: check your FXML file...";
firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("test"));
lastNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));
testColumn.setCellValueFactory(new PropertyValueFactory<>("lastName"));
objDbClass = new DBClass();
try{
con = objDbClass.getConnection();
buildData();
tableView.setRowFactory(
(TableView<Person> tableView1) -> {
final TableRow<Person> row = new TableRow<>();
final ContextMenu rowMenu = new ContextMenu();
MenuItem editItem = new MenuItem("Edit");
MenuItem removeItem = new MenuItem("Delete");
removeItem.setOnAction((ActionEvent event) -> {
tableView1.getItems().remove(row.getItem());
});
rowMenu.getItems().addAll(editItem, removeItem);
row.contextMenuProperty().bind(
Bindings.when(Bindings.isNotNull(row.itemProperty()))
.then(rowMenu)
.otherwise((ContextMenu)null));
return row;
});
tableView.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
if (e.getButton() == MouseButton.SECONDARY)
resultadoContextMenu.show(tableView, e.getScreenX(), e.getScreenY());
});
}
catch(ClassNotFoundException | SQLException ce){
}
}
//Populate table
public void buildData(){
data = FXCollections.observableArrayList();
try{
String SQL = "Select * from tbltest Order By test";
ResultSet rs = con.createStatement().executeQuery(SQL);
while(rs.next()){
Person cm = new Person();
cm.setFirstName(rs.getString("test"));
cm.setLastName(rs.getString("nombre"));
cm.setTest(rs.getString("apellido"));
data.add(cm);
}
tableView.setItems(data);
tableView.getItems();
}
catch(SQLException e){
System.out.println("Error on Building Data");
}
}
}
I'm using Scene builder and my FXML file is:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.paint.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.cell.*?>
<?import javafx.collections.*?>
<?import fxmltableview.*?>
<!--/*<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxmltableview.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>*/-->
<GridPane alignment="CENTER" hgap="10.0" prefHeight="689.0" prefWidth="710.0" vgap="10.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxmltableview.FXMLTableViewController">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<children>
<Button mnemonicParsing="false" text="Button" GridPane.rowIndex="1">
<effect>
<DropShadow />
</effect>
</Button>
<Label style="-fx-font: NORMAL 20 Tahoma;" text="Address Book" textOverrun="CENTER_ELLIPSIS" GridPane.rowIndex="2">
<font>
<Font name="Gill Sans MT Bold" size="13.0" />
</font>
<textFill>
<LinearGradient endX="1.0" endY="1.0" startX="0.5769230769230769">
<stops>
<Stop color="BLACK" />
<Stop color="WHITE" offset="1.0" />
</stops>
</LinearGradient>
</textFill></Label>
<TableView fx:id="tableView" prefHeight="265.0" prefWidth="502.0" tableMenuButtonVisible="true" GridPane.columnIndex="0" GridPane.rowIndex="3">
<columns>
<TableColumn fx:id="firstNameColumn" prefWidth="100" text="First Name">
<cellValueFactory>
<PropertyValueFactory property="firstName" />
</cellValueFactory>
<contextMenu>
<ContextMenu fx:id="resultadoContextMenu">
<items>
<MenuItem mnemonicParsing="false" text="Unspecified Action" />
</items>
</ContextMenu>
</contextMenu>
</TableColumn>
<TableColumn fx:id="lastNameColumn" prefWidth="100" text="Last Name">
<cellValueFactory>
<PropertyValueFactory property="lastName" />
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="testColumn" prefWidth="300" text="Email Address">
<cellValueFactory>
<PropertyValueFactory property="test" />
</cellValueFactory>
</TableColumn>
</columns>
<items>
<FXCollections fx:factory="observableArrayList">
<!--/* <Person email="jacob.smith#example.com" firstName="Jacob" lastName="Smith" />
<Person email="isabella.johnson#example.com" firstName="Isabella" lastName="Johnson" />
<Person email="ethan.williams#example.com" firstName="Ethan" lastName="Williams" />
<Person email="emma.jones#example.com" firstName="Emma" lastName="Jones" />
<Person email="michael.brown#example.com" firstName="Michael" lastName="Brown" />/*-->
</FXCollections>
</items>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
<columnConstraints>
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints />
<RowConstraints />
<RowConstraints />
<RowConstraints />
</rowConstraints>
</GridPane>

You have null condition to show your context menu. Add data to your tableView and click on row. (I think your ResultSet is empty)
tableView.setItems(data);

Related

Load URL from ImageView

I need to load a URL inside my app with the click of an ImageView. I get the app to load until I start trying to assign intents (on the MainActivity.java) to my ImageViews (on activity_main.xml).
I have tried ImageButton vs ImageView; and both come with their own set of issues I can't seem to find answers to. I finally gave up on the imageButton and am now trying my luck at ImageView. All Android components are up-to-date which includes the software itself, the gradle, and plugins.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/mainBackground"
tools:context=".MainActivity">
<ImageView
android:id="#+id/s"
android:layout_width="0dp"
android:layout_height="0dp"
android:clickable="true"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="16dp"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="#+id/y"
app:layout_constraintEnd_toStartOf="#+id/v"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/s"
tools:visibility="visible" />
<ImageView
android:id="#+id/v"
android:layout_width="0dp"
android:layout_height="0dp"
android:clickable="true"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="#+id/q"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/s"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/v"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.app.sega;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import java.net.URI;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView img_s = (ImageView) findViewById(R.id.s);
img.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse("http://southeastgeorgiatoday.com"));
startActivity(intent);
}
});
ImageView img_v = (ImageView) findViewById(R.id.q);
img.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse("http://us7.maindigitalstream.com/2780/"));
startActivity(intent);
}
});
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.app.sega" >
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<data android:scheme="http" android:host="www.southeastgeorgiatoday.com" />
<data android:scheme="http" android:host="us7.maindigitalstream.com/2780/" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The objective is to open the url of the intent inside the app with the click of the referenced ImageView. But since including this intent script on the MainActivity.java it will not build, let alone install and launch. I have tried it both on the virtual and actual device via Android's Emulator and it will not install on either.
Here is the error message I get from the LogCat during the build process...
C:\Users\webwi\Documents\_MobileApps\SEGA\app\src\main\java\com\app\sega\MainActivity.java:23: error: cannot find symbol
img.setOnClickListener(new View.OnClickListener() {
^
symbol: variable img
location: class MainActivity
C:\Users\webwi\Documents\_MobileApps\SEGA\app\src\main\java\com\app\sega\MainActivity.java:33: error: cannot find symbol
img.setOnClickListener(new View.OnClickListener() {
^
symbol: variable img
location: class MainActivity
2 errors
Also, it might be worth mentioning in both of the intent lines that begin with "img.setOnClickListener..." the 'img' before the '.' is red.
Obviously there is something wrong with my intents, I'm just not sure what? Any advice.

English font working but non-English (Hindi) font not displaying in webview

An English font is working in HTML in webview, but the non-English font (Hindi) is not displaying in HTML in webview.
Here is my source code.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="in.wptrafficanalyzer.webviewcustomfont"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="in.wptrafficanalyzer.webviewcustomfont.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
demo.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;" charset="UTF-8">
<style>
/** Specify a font named "MyFont",
and specify the URL where it can be found: */
#font-face {
font-family: "MyFont";
src: url('file:///android_asset/fonts/BLKCHCRY.TTF');
}
h2 { font-family:"MyFont"}
#font-face {
font-family: "MyFontSD";
src: url('file:///android_asset/fonts/SHREE-DEV7-1076H.TTF');
}
h1 { font-family:"MyFontSD"}
</style>
</head>
<body>
<h2>
Welcome to BLACK CHANCERY FONT
</h2>
<h1>
1234567890
Am{X
</h1>
</body>
</html>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<WebView
android:id="#+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_world" />
</RelativeLayout>
MainActivity.java
package in.wptrafficanalyzer.webviewcustomfont;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.webkit.WebView;
public class MainActivity extends Activity {
WebView mWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Getting reference to WebView of the activity_main layout
mWebView = (WebView) findViewById(R.id.webview);
// Loading an HTML page into webview
mWebView.loadUrl("file:///android_asset/demo.html");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Note:
HTML file demo.html is copied in the assets folder
BLKCHCRY.TTF font file is copied in fonts folder
SHREE-DEV7-1076H.TTF font file is copied in fonts folder
Link to download fonts (SHREE-DEV7-1076H.TTF and BLKCHCRY.TTF)

FireFox Extension XulSchool - Adding Events and Commands - on load function

I'm trying to edit the helloworld from this tutorial:
https://developer.mozilla.org/en-US/Add-ons/Overlay_Extensions/XUL_School/Getting_Started_with_Firefox_Extensions
So, I need to execute a function when page loads, this part of the tutorial explains how to do that:
https://developer.mozilla.org/en-US/Add-ons/Overlay_Extensions/XUL_School/Adding_Events_and_Commands
I edited the browserOverlay.js file, I writed the init function and that listener at the end of the code:
/**
* XULSchoolChrome namespace.
*/
if ("undefined" == typeof(XULSchoolChrome)) {
var XULSchoolChrome = {};
};
/**
* Controls the browser overlay for the Hello World extension.
*/
XULSchoolChrome.BrowserOverlay = {
init : function(event) {
window.alert('aaaaeeee');
},
/**
* Says 'Hello' to the user.
*/
sayHello : function(aEvent) {
let stringBundle = document.getElementById("xulschoolhello-string-bundle");
let message = stringBundle.getString("xulschoolhello.greeting.label");
window.alert(message);
}
};
window.addEventListener("load", function() {
//window.removeEventListener("load", onFirefoxLoadEvent, false); // remove listener, no longer needed
XULSchoolChrome.BrowserOverlay.init();
}, false);
and I edited the broserOverlay.xul, I writed the onload propertie at overlay tag:
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin/" ?>
<?xml-stylesheet type="text/css"
href="chrome://xulschoolhello/skin/browserOverlay.css" ?>
<!DOCTYPE overlay SYSTEM
"chrome://xulschoolhello/locale/browserOverlay.dtd">
<overlay id="xulschoolhello-browser-overlay"
onload="XulSchoolChrome.BrowserOverlay.init();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript"
src="chrome://xulschoolhello/content/browserOverlay.js" />
<stringbundleset id="stringbundleset">
<stringbundle id="xulschoolhello-string-bundle"
src="chrome://xulschoolhello/locale/browserOverlay.properties" />
</stringbundleset>
<menubar id="main-menubar">
<menu id="xulschoolhello-hello-menu" label="&xulschoolhello.hello.label;"
accesskey="&xulschoolhello.helloMenu.accesskey;" insertafter="helpMenu">
<menupopup>
<menuitem id="xulschoolhello-hello-menu-item"
label="&xulschoolhello.hello.label;"
accesskey="&xulschoolhello.helloItem.accesskey;"
oncommand="XULSchoolChrome.BrowserOverlay.sayHello(event);" />
</menupopup>
</menu>
</menubar>
<vbox id="appmenuSecondaryPane">
<menu id="xulschoolhello-hello-menu-2" label="&xulschoolhello.hello.label;"
accesskey="&xulschoolhello.helloMenu.accesskey;"
insertafter="appmenu_addons">
<menupopup>
<menuitem id="xulschoolhello-hello-menu-item-2"
label="&xulschoolhello.hello.label;"
accesskey="&xulschoolhello.helloItem.accesskey;"
oncommand="XULSchoolChrome.BrowserOverlay.sayHello(event);" />
</menupopup>
</menu>
</vbox>
</overlay>
It does not alert on page loads.... why?

sapui5 odata binding in controller

I am building app on demo MyFiorri application and I have problem binding data using ODATA. I defined odata in component.js
jQuery.sap.declare("sap.ui.demo.myFiori.Component");
sap.ui.core.UIComponent.extend("sap.ui.demo.myFiori.Component", {
createContent : function() {
// create root view
var oView = sap.ui.view({
id : "app",
viewName : "sap.ui.demo.myFiori.view.App",
type : "JS",
viewData : { component : this }
});
// set i18n model
var i18nModel = new sap.ui.model.resource.ResourceModel({
bundleUrl : "i18n/messageBundle.properties"
});
oView.setModel(i18nModel, "i18n");
// // Using OData model to connect against a real service
var url = "http://localhost:8080/serveris/SERVERIS.svc/";
var oModel = new sap.ui.model.odata.ODataModel(url, true, "", "");
oView.setModel(oModel);
sap.ui.getCore().setModel(oModel);
// set device model
var deviceModel = new sap.ui.model.json.JSONModel({
isTouch : sap.ui.Device.support.touch,
isNoTouch : !sap.ui.Device.support.touch,
isPhone : sap.ui.Device.system.phone,
isNoPhone : !sap.ui.Device.system.phone,
listMode : sap.ui.Device.system.phone ? "None" : "SingleSelectMaster",
listItemType : sap.ui.Device.system.phone ? "Active" : "Inactive"
});
deviceModel.setDefaultBindingMode("OneWay");
oView.setModel(deviceModel, "device");
// done
return oView;
}
});
Now, I need to read these data:
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xml:base="http://localhost:8080/serveris/SERVERIS.svc/">
<script id="tinyhippos-injected"/>
<id>http://localhost:8080/serveris/SERVERIS.svc/Users</id>
<title type="text">Users</title>
<updated>2014-05-27T18:07:01.403+03:00</updated>
<author>
<name/>
</author>
<link href="Users" rel="self" title="Users"/>
<entry>
<id>
http://localhost:8080/serveris/SERVERIS.svc/Users(0)
</id>
<title type="text">Users</title>
<updated>2014-05-27T18:07:01.404+03:00</updated>
<category term="serveris.User" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<link href="Users(0)" rel="edit" title="User"/>
<link href="Users(0)/TasklistDetails" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/TasklistDetails" title="TasklistDetails"type="application/atom+xml;type=feed"/>
<content type="application/xml">
<m:properties>
<d:Login>jonas</d:Login>
<d:Passw>saugus</d:Passw>
<d:UserId>0</d:UserId>
</m:properties>
</content>
</entry>
<entry>
<id>
http://localhost:8080/serveris/SERVERIS.svc/Users(1)
</id>
<title type="text">Users</title>
<updated>2014-05-27T18:07:01.405+03:00</updated>
<category term="serveris.User" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<link href="Users(1)" rel="edit" title="User"/>
<link href="Users(1)/TasklistDetails" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/TasklistDetails" title="TasklistDetails"type="application/atom+xml;type=feed"/>
<content type="application/xml">
<m:properties>
<d:Login>petras</d:Login>
<d:Passw>pass</d:Passw>
<d:UserId>1</d:UserId>
</m:properties>
</content>
</entry>
</feed>
I made login.view.xml and login.controller.js in which i want ta access these data
login.view.xml
<core:View
controllerName="sap.ui.demo.myFiori.view.login"
xmlns="sap.m"
xmlns:l="sap.ui.layout"
xmlns:core="sap.ui.core" >
<Page
title="{i18n>LoginIn}">
<VBox
class="marginBoxContent" >
<items>
<Label text="username" />
<Input
id="nameInput"
type="Text"
placeholder="enter username ..." />
<Label text="Pasword" />
<Input
id="passwInput"
type="Password"
placeholder="enter password..." />
<Button text="Prisijungti" press="handleContinue" />
</items>
</VBox>
</Page>
</core:View>
login.controller.js
jQuery.sap.require("sap.ui.demo.myFiori.util.Formatter");
sap.ui.controller("sap.ui.demo.myFiori.view.login", {
handleContinue : function (evt) {
// var authinfo = this.getCore().getModel().getData().Users[0]; In this line I should get data
var name = this.getView().byId("nameInput").getValue();
var paswd = this.getView().byId("passwInput").getValue();
if (name == "authinfo.login" && paswd == "authinfo.passw") {
var context = evt.getSource().getBindingContext();
this.nav.to("Master", context);
}
else {
jQuery.sap.require("sap.m.MessageToast");
sap.m.MessageToast.show("there is no such user or bad login data");
}
}
});
I hope I clearly described my problem.
Put a debug breakpoint in handleContinue function and try to see what shows up in log for sap.ui.getCore().getModel().getData().
If you're able to log something, try to see this way in console:
var theModel = sap.ui.getCore().getModel()
theModel.oData
See what you get as the output and then you can continue.

How to construct a settings page similar to the stock one in Windows Phone 7?

When I launch the Windows Phone Settings app, what is presented is a pivot control with a bunch of items on each page. For example, the first item is:
THEME
blue
What is the standard way of creating these items? I want them to have the same font style and look. Is there any control to represent the item above?
Thanks!
It is a ListBox control and a DataTemplate for eacht item. The template defines two TextBox controls, one for the 'title' and one for a 'description/value'. You can set the style for each TextBox.
Edit: here's an example code
<ListBox x:Name="YourListBox" Margin="0" ItemsSource="{Binding YourItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding ItemTitle}" TextWrapping="Wrap" Style="{StaticResource PhoneTextTitle2Style}"/>
<TextBlock Text="{Binding ItemValue}" TextWrapping="Wrap" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
After playing with this for 2 hours pixel by pixel and using a paint program to compare screenshots with the real thing side by side (there's gotta be a better way!), I found the following solution.
Here is the settings page replicated exactly. I've created a custom user control so that adding an item to xaml is as easy as this:
<MyApp:SettingsItem Label="theme" Sub="blue"/>
Here's the code:
SettingsItem.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace MyApp
{
// This custom control class is to show a standard item in a settings page.
public partial class SettingsItem : UserControl
{
private const string TAG = "SettingsItem";
public SettingsItem()
{
// Required to initialize variables
InitializeComponent();
}
public static readonly DependencyProperty LabelProperty =
DependencyProperty.Register(
"Label",
typeof(string),
typeof(SettingsItem),
new PropertyMetadata(new PropertyChangedCallback
(OnLabelChanged)));
public string Label
{
get
{
return (string)GetValue(LabelProperty);
}
set
{
SetValue(LabelProperty, value);
}
}
private static void OnLabelChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
SettingsItem item = (SettingsItem)d;
string newValue = (string)e.NewValue;
item.m_label.Text = newValue.ToLower();
}
public static readonly DependencyProperty SubProperty =
DependencyProperty.Register(
"Sub",
typeof(string),
typeof(SettingsItem),
new PropertyMetadata(new PropertyChangedCallback
(OnSubChanged)));
public string Sub
{
get
{
return (string)GetValue(SubProperty);
}
set
{
SetValue(SubProperty, value);
}
}
private static void OnSubChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
SettingsItem item = (SettingsItem)d;
string newValue = (string)e.NewValue;
item.m_sub.Text = newValue;
}
}
}
SettingsItem.xaml
<UserControl
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"
x:Class="MyApp.SettingsItem"
d:DesignWidth="428" d:DesignHeight="0">
<Grid x:Name="LayoutRoot" Background="Transparent">
<StackPanel
Orientation="Vertical"
>
<TextBlock
x:Name="m_label"
Text="label"
Style="{StaticResource PhoneTextExtraLargeStyle}"
Margin="0, 18, 0, 0"
/>
<TextBlock
x:Name="m_sub"
Text="Sub"
Style="{StaticResource PhoneTextSubtleStyle}"
TextWrapping="Wrap"
Margin="0, -6, 0, 0"
/>
</StackPanel>
</Grid>
</UserControl>
and here's the page xaml:
<phone:PhoneApplicationPage
x:Class="MyApp.SettingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
xmlns:MyApp="clr-namespace:MyApp;assembly=MyApp"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<!--Pivot Control-->
<controls:Pivot Title="MY APP" SelectedIndex="0">
<controls:PivotItem
Name="PIVOT_GENERAL"
Margin="0"
Header="settings">
<Grid Margin="26,9,0,0">
<StackPanel>
<MyApp:SettingsItem
Label="theme"
Sub="blue"
/>
<MyApp:SettingsItem
Label="date+time"
Sub="UTC-08 Pacific Time (US + Canada)"
/>
<MyApp:SettingsItem
Label="region+language"
Sub="United States"
/>
</StackPanel>
</Grid>
</controls:PivotItem>
</controls:Pivot>
</Grid>
</phone:PhoneApplicationPage>
My suggestion:
<Button>
<Button.Template>
<ControlTemplate>
<StackPanel>
<TextBlock Text="Label" Style="{StaticResource PhoneTextExtraLargeStyle}" Margin="0 18 0 0"/>
<TextBlock Text="Sub" Style="{StaticResource PhoneTextSubtleStyle}" Margin="0 -6 0 0"/>
</StackPanel>
</ControlTemplate>
</Button.Template>

Resources