Создание взаимодействующих с сервером приложений в Silverlight
Все элементы UI размещаются в контейнере и все они должны иметь в XAML уникальные имена. Как видите, в этом примере XAML имя каждого TextBlock определятся атрибутом x:Name. При клонировании контейнера XAML должен обеспечивать уникальные имена для этих узлов. Алгоритм присваивания имен будет прост- в конце каждого имени будет добавляться индекс элемента. Итак, например, записанное в шаблоне значение x:Name txtState для первой строки базы данных превратиться в txtState1, для второй строки - txtState2, и т.д.
Как будет показано в следующем разделе, размножить эти элементы в PHP очень просто.
Формирование XAML из PHP и MySQL
Синтаксический разбор страницы выполняет PHP. Это означает, что когда сервер получает запрос на страницу, PHP записывает форматированные данные в буфер ответов. Когда PHP встречает специальный открывающий тег ( <?php ), он передает обработку синтаксическому анализатору PHP. Анализатор выполняет код, выявляемый процессором PHP, пока не встретит закрывающий тег ( ?> ). Это делает связку MySQL и PHP идеальным сочетанием для отображения содержимого, формируемого по шаблону. Шаблон для формирования содержимого просто помещается в файл с расширением .php, а там, где требуется вставить некоторые связанные с данными поля подстановки, добавляется необходимая PHP-логика, заключенная в открывающий и закрывающий теги ( <?php и ?>, соответственно).
PHP-код может содержать циклы. Если после выражения цикла следует некоторое содержимое, оно будет выведено многократно. В теле цикла могут присутствовать открывающий/закрывающий теги РНР. Например, можно сделать следующее:
<?php for($i =0; $i<100; $i ++) { // Открывающая скобка цикла // Выходим из PHP, хотя цикл еще не закрыт! ?> <H1>My Text Line is <?php echo $i; ?></H1> <?php } // Теперь закрываем наш цикл ?>
Это обеспечит повторение HTML-содержимого (текста, заключенного в элемент <H1> ) 100 раз. Как видите, не обязательно заключать весь текст в теги <?php ... ?>. Это полезное свойство при объединении PHP и XAML
В XAML холст-контейнер может быть помещен в цикл:
<?php for($i =0; $i<100; $i ++) { // Открывающая скобка цикла // Выходим из PHP, хотя цикл еще не закрыт! ?> <Canvas> ... </Canvas> <?php } // Теперь закрываем наш цикл ?>
Выполнение этого кода обеспечит запись XAML 100 раз! Это делает PHP мощным языком описания шаблонов для Silverlight.
Возвращаясь к нашему примеру, рассмотрим, как установить подключение к базе данных, выполнить запрос к ней и записать то количество XAML-элементов Canvas, которое соответствует числу возвращенных результатов. Также отредактируем содержимое элементов TextBlock холста-контейнера, чтобы они отображали информацию, полученную из базы данных, а также обеспечим уникальность имен TextBlock.
В итоге должна получиться PHP-страница, формирующая XAML, который будет использоваться как источник для элемента управления Silverlight. Но чтобы было немного интересней, изменим PHP и введем параметр state (штат), который обеспечит возвращение сведений только для людей, проживающих в заданном штате. Это превратит наш код в настоящий динамический генератор XAML
Во-первых, необходимо, чтобы Silverlight распознавал вывод PHP какXML. Для этого задаем тип MIME содержимого вывода. Это делается в PHP с помощью команды header (заголовок):
header('Content-type: text/xml');
Извлечение параметра строки запроса (т.е. http://server/script.php?param =value) в PHP обеспечивается массивом $ REQUEST. Итак, чтобы прочитать значение параметра State, используем следующий код:
$State=$ REQUEST['State'];
В PHP версии 4.x имеется встроенный набор команд MySQL Для версий 5.x и выше набор команд MySQL должен задаваться как расширение. Независимо от используемой версии, синтаксис PHP аналогичен.
Подключение к серверу localhost с использованием имени пользователя user и пароля password выполняется с помощью команды mysql connect:
$con = mysql connect("localhost", "user", "password");
На сервере может располагаться несколько баз данных. Для выбора необходимой базы данных используется команда mysql select db:
mysql select db("test", $con); // "test" имя базы данных
Затем, чтобы выполнить запрос к этой базе данных, используется команда mysql query, в которую передается строка, содержащая фактический запрос SQL Результат запроса будет представлять собой массив массивов значений. Приведем пример:
$sqlString = "SELECT * from addresses"; $result = mysql query($sqlString);
Затем массив mysql fetch array разбивается на строки. С помощью цикла while можно обойти каждую строку, как показано в следующем примере:
while($row = mysql fetch array($result)) { ... }
таким образом, исходя из данного сценария, получаем такой алгоритм действий:
Задаем тип MIME text/xml. Принимаем входной параметр (штат). Записываем начальный тег "корневого" Canvas. Используем входной параметр для построения запроса. Выполняем запрос и получаем результирующее множество. Для каждой строки результирующего множества:
- a. Создаем XAML-шаблона.
- b. Заполняем атрибуты Text элементов TextBlock данными из соответствующих полей базы данных.
- c. Заполняем атрибуты x:Name уникальными ID, полученными на основании порядкового номера
строки.
Закрываем тег "корневого" Canvas.
Код PHP-страницы полностью приведен в листинге 10.2. Разметка PHP в блоке XAML выделена жирным шрифтом.
<?php header('Content-type: text/xml'); $State=$ REQUEST['State']; ?> <Canvas xmlns=" http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xam l" Width="640" Height="480" Background = "#FF460608"> <?php $height=128; $top=8; $i=0; $con = mysql connect("localhost", "root", "root"); mysql select db("test",$con); $sqlString = "SELECT * from addresses"; if($State! = "") { $sqlString = $sqlString . " WHERE State = '" . $State . "'"; } $result = mysql query($sqlString); while($row = mysql fetch array($result)) { ?> <Canvas Width="352" Height="128" Canvas.Left="10" Canvas.Top =" <"?php echo($top="" + ($height*$i="")); ?>" > <Rectangle Fill="#FF693B3D" Stroke="#FF000000" StrokeThickness="0" RadiusX="16" RadiusY="16" Width = "352" Height="128" Canvas.Top="1"/> <Rectangle Stroke="#FF000000" StrokeThickness="0" RadiusX="8" RadiusY="8" Width="336" Height="40" Canvas.Left="8" Canvas.Top="8"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.518,0.175" StartPoint="0.515,0.825"> <GradientStop Color="#FF460608" Offset="0"/> <GradientStop Color="#FF841316" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> <TextBlock x:Name="txtName"<?php echo="" $i=""; ?>" Width="312" Height="24" Canvas.Left="16" Canvas.Top="16" FontFamily="Arial Unicode MS" FontSize="18" FontWeight="Normal" Foreground="#FFFFFFFF" Text="<?php echo($row['Name']); ?>" TextWrapping ="Wrap"/> <Rectangle Stroke="#FF000000" StrokeThickness="0" RadiusX="8" RadiusY="8" Width="336" Height="23" Canvas.Left="8" Canvas.Top="48"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.518,0.175" StartPoint="0.515,0.825"> <GradientStop Color="#FF460608" Offset="0"/> <GradientStop Color="#FF841316" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> <TextBlock x:Name="txtAddr1" <?php echo="" $i=""; ?>" Width="312" Height="24" FontFamily="Arial Unicode MS" FontSize="12" FontWeight="Normal" Foreg round="#FFFFFFFF" Text="<?php echo($row['Address1']); ?>" TextWrapping ="Wrap" Canvas.Left="14" Canvas.Top="48"/> <Rectangle Stroke="#FF000000" StrokeThickness="0" RadiusX="8" RadiusY="8" Width="336" Height="23" Canvas.Left="8" Canvas.Top="71"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.518,0.175" StartPoint="0.515,0.825"> <GradientStop Color="#FF460608" Offset="0"/> <GradientStop Color="#FF841316" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> <TextBlock x:Name="txtAddr2" <?php echo="" $i=""; ?>" Width = "312" Height="24" FontFamily="Arial Unicode MS" FontSize="12" FontWeight="Normal" Foreground="#FFFFFFFF" Text="<?php echo($row['Address2']); ?>" TextWrapping="Wrap" Canvas.Left="15" Canvas.Top="72"/> <Rectangle Stroke="#FF000000" StrokeThickness="0" RadiusX="8" RadiusY="8" Width="168" Height="23" Canvas.Left="176" Canvas.Top="94"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.518,0.175" StartPoint="0.515,0.825"> <GradientStop Color="#FF460608" Offset="0"/> <GradientStop Color="#FF841316" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> <Rectangle Stroke="#FF000000" StrokeThickness="0" RadiusX="8" RadiusY="8" Width="168" Height="23" Canvas.Left="8" Canvas.Top="94"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.518,0.175" StartPoint="0.515,0.825"> <GradientStop Color="#FF460608" Offset="0"/> <GradientStop Color="#FF841316" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> <TextBlock x:Name="txtCity" <?php echo="" $i=""; ?>" Width = "144" Height="24" FontFamily="Arial Unicode MS" FontSize="12" FontWeight="Normal" Foreground="#FFFFFFFF" Text="<?php echo($row['City']); ?>" TextWrapping= "Wrap" Canvas.Left="15" Canvas.Top="96"/> <TextBlock x:Name="txtState" <?php echo="" $i=""; ?>" Width="144" Height="24" FontFamily="Arial Unicode MS" FontSize="12" FontWeight="Normal" Foreground="#FFFFFFFF" Text="<?php echo($row['State']); ?>" TextWrapping = "Wrap" Canvas.Left="182" Canvas.Top="96"/> </Canvas> <?php $i++; }?> </Canvas>Листинг 10.2. 2 PHP код для формирования XAML
Создание PHP-страницы для отображения Silverlight
Как было показано в предыдущем разделе, сервер выводит содержимое напрямую, пока не встречает открывающий тег ( <?php ). Встретив этот тег, сервер обращается к интерпретатору PHP, который выполняет код, заключенный в открывающий и закрывающий теги ( ?> ).
PHP-код обычно используется для создания динамического HTML-кода. Поскольку Silverlight отображается с помощью HTML, HTML-страница просто редактируется: в нее добавляются теги PHP, и меняется имя файла с добавлением расширения .php. Итак, чтобы реализовать отображение Silverlight, используя PHP, необходимо, чтобы страница, включающая Silverlight.js и createSilverlight.js, вызывала createSilverlight для создания экземпляра элемента управления Silverlight.
Мы хотим, чтобы пользователь мог выбирать имена и адреса в базе данных по штату. Таким образом, эта страница должна принимать параметр и применять его при создании содержимого Silverlight с использованием XAML-источника, сформированного PHP, который был представлен в предыдущем разделе. К счастью, это очень просто сделать в PHP. Чтобы вывести на экран, сформированный XAML, необходимо всего лишь присвоить в качестве значения свойства content элемента управления Silverlight Uniform Resource Indicator (URI) вашего приложения. Silverlight будет подключаться к серверу по этому URI, принимать результирующий XAML и формировать его визуальное представление.
Далее представлен полный код примера PHP-страницы, формирующей HTML:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>SilverlightJSApplication2</title> <script type="text/javascript" src="Silverlight.js"> </script> <script type="text/javascript" src="createSilverlight.js"> </script> <script type="text/javascript"> function handleLoad(control, userContext, rootElement) { <?php if(!isset($_REQUEST['State'])) $State=""; else $State=$_REQUEST['State']; ?> control.source = "http://localhost/phptest/xaml.php?State= <?php echo($State) ?>"; } </script> </head> <body> <div id="SilverlightControlHost"> <script type="text/javascript"> createSilverlight(); </script> </div> </body> </html>
На рис. 10.6 и 10-7 показано, как эта PHP-страница отображается в браузере с использованием Silver-light для адресов в Нью-Йорке (NY в базе данных) и Вашингтоне (WA).