Многостраничные приложения в Silverlight - Более практичное использование

ОГЛАВЛЕНИЕ

Более практичное использование

Теперь, когда у нас есть основная архитектура, нам остается всего лишь создать полезные страницы для переключения. Как уже обсуждалось, мы создадим три страницы - первая будет генерировать список слов, которые будут использовать другие две.

Начнем с создания нового решения PageSwitching. Как только это будет открыто в Visual Studio, скопируйте файлы App.xaml.cs, ISwitchable.cs, PageSwitcher.xaml, PageSwitcher.xaml.cs и Switcher.cs из PageSwitch в новую директорию.

App.xaml.cs перепишет тот файл, что был создан Visual Studio (убедитесь в том, что вы настроили пространство имен файла), все остальные файлы будут новыми, и потому вам надо будет добавить их в ваш проект щелкнув правой кнопкой мыши по нему в Solution Explorer и выбрав пункт добавления нового элемента (Add Existing Item),

Рисунок 8-6. Добавление существующих элементов

Удалите Page.xaml и Page.xaml.cs и добавьте три новых UserControls: Find, Search и Count. Вот что у вас должно получиться после всего этого :

Рисунок 8-7. Проект PageSwitching

Давайте добавим внешний вид для страницы Find - первая страница, используемая для создания списка слов.

Вот Xaml, который я использовал для создания внешнего вида файла, но вы можете создать свой,

<UserControl x:Class="PageSwitching.Find"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="500" Height="600">
  <Grid
    x:Name="LayoutRoot"
    Background="White">
    <Grid.RowDefinitions>
      <RowDefinition
        Height="0.078*" />
      <RowDefinition Height="0.072*"/>
      <RowDefinition
        Height="0.85*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition
        Width="0.5*" />
      <ColumnDefinition
        Width="0.5*" />
    </Grid.ColumnDefinitions>
    <TextBlock
      x:Name="Message"
      Text="Ready..."
      TextWrapping="Wrap"
      FontFamily="Georgia"
      FontSize="18"
      VerticalAlignment="Bottom"
      HorizontalAlignment="Left"
      Visibility="Visible" Grid.Row="1" />
    <ScrollViewer
      x:Name="WordDisplayViewer"
      BorderBrush="Black"
      BorderThickness="1"
      Grid.Row="2"
      Grid.Column="0"
      Margin="5,10,0,2"
      Background="Bisque"
      VerticalScrollBarVisibility="Auto"
      HorizontalScrollBarVisibility="Hidden"
      VerticalAlignment="Stretch"
      Width="240"
      HorizontalAlignment="Left"
      Visibility="Visible">
      <TextBlock
        x:Name="WordDisplay"
        TextWrapping="Wrap"
        Text="WordDisplay"
        Width="160" />
    </ScrollViewer>
    <ScrollViewer
      x:Name="SortDisplayViewer"
      BorderBrush="Black"
      BorderThickness="1"
      Grid.Row="2"
      Grid.Column="1"
      Margin="0,10,8,0"
      Width="240"
      Background="Wheat"
      VerticalScrollBarVisibility="Auto"
      HorizontalScrollBarVisibility="Hidden"
      VerticalAlignment="Stretch"
      HorizontalAlignment="Right"
      Visibility="Visible">
      <TextBlock
        x:Name="SortDisplay"
        TextWrapping="Wrap"
        Width="160"
        Text="SortDisplay" />
    </ScrollViewer>
    <StackPanel
      Height="Auto"
      VerticalAlignment="Stretch"
      Grid.Column="1"
      Orientation="Horizontal" Grid.RowSpan="2">
      <Button
        x:Name="FilePicker"
        Content="Pick a file"
        Width="100"
        Background="#FF00FF00"
        FontFamily="Georgia"
        FontSize="18"
        Height="35" HorizontalAlignment="Center"
VerticalAlignment="Center" />
      <Grid Height="Auto" x:Name="ButtonGrid" Width="153">
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="0.5*"/>
          <ColumnDefinition Width="0.5*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="0.5*"/>
          <RowDefinition Height="0.5*"/>
        </Grid.RowDefinitions>
        <Button
    x:Name="SearchPage"
    Content="Search"
    Background="#FFFF0000"
    FontFamily="Georgia"
    FontSize="18"
    Margin="5,0,5,0"
    Visibility="Visible"
          HorizontalAlignment="Center"
          VerticalAlignment="Center"
          Grid.ColumnSpan="1"
          Grid.RowSpan="2" />
        <Button
    x:Name="CountPage"
    Content="Count"
    Background="#FFFF0000"
    FontFamily="Georgia"
    FontSize="18"
    Visibility="Visible"
          VerticalAlignment="Center"
          Grid.Row="0"
          Grid.Column="1"
          HorizontalAlignment="Center"
          Grid.RowSpan="2" />
      </Grid>
    </StackPanel>
  </Grid>
</UserControl>

Вот как это выглядит

Рисунок 8-8. Поиск страницы

Find.xaml.cs должен реализовывать обработчики событий трех кнопок,

public Find()
{
  InitializeComponent();
  FilePicker.Click += new RoutedEventHandler( FilePicker_Click );
  SearchPage.Click += new RoutedEventHandler( ChangePage );
  CountPage.Click +=new RoutedEventHandler( ChangePage );

Обратите внимание на то, что кнопки SearchPage и CountPage имеют общий обработчик события потому, что их реализация очень схожа,

void ChangePage( object sender, RoutedEventArgs e )
{
  Button b = e.OriginalSource as Button;
  string btnName = b.Content.ToString().ToUpper();
  if ( btnName == "SEARCH" )
    Switcher.Switch( new SearchPage(), SortedWords );
  else
    Switcher.Switch( new CountPage(), SortedWords );
}

Логика здесь заключается в преобразовании свойства OriginalSource, принадлежащего Event Argument, в тип Button, и затем использовании для того, чтобы извлечь верхний регистр из содержимого кнопки. Мы затем сравниваем это со словом при поиске, и если они совпадут  - мы вызываем метод Switch для страницы SearchPage (либо для CountPage) и передаем SortedWords, который является набором слов, необходимых для новой страницы.

Мы собираем данные слова путем прохода по большому документу и выдергивая все уникальные слова из него. Вы можете взять любой текстовый файл и положить его в соответствующий каталог на диске. Когда пользователь нажмет на кнопку выбора файла (Pick A File), обработчик события откроет диалоговое окно и попросит выбрать файл,

void FilePicker_Click( object sender, RoutedEventArgs e )
 {
   FilePicker.IsEnabled = false;
   OpenFileDialog openFileDialog1 = new OpenFileDialog();
   openFileDialog1.Filter = "Text Files (.txt)|*.txt|All Files (*.*)|*.*";
   openFileDialog1.FilterIndex = 1;
   openFileDialog1.Multiselect = false;
   bool? userClickedOK = openFileDialog1.ShowDialog();

Если пользователь нажмет на файл и затем кнопку OK - значение логической переменной userClickedOK будет равно true. На данном этапе вам нужно открыть streamReader по отношению к файлу для того, чтобы считать его содержимое в StringBuilder, прочитав все до конца файла, и добавляя каждую строку в ваш StringBuilder,

if ( userClickedOK == true )
{
   // Ограничение количества считываемого
  const long MAXBYTES = 2000; // 200000
  System.IO.FileInfo file = openFileDialog1.File;
  StringBuilder sb = new StringBuilder();
 
  if ( file != null )
  {
    System.IO.Stream fileStream = file.OpenRead();
    using ( System.IO.StreamReader reader =
               new System.IO.StreamReader( fileStream ) )
    {
      string temp = string.Empty;
 
      // соединение со строкой, пока у вас есть что считать
      // и вы не дошли до лимита MAXBYTES
      try
      {
        do
        {
          temp = reader.ReadLine();
          sb.Append( temp );
        } while ( temp != null && sb.Length < MAXBYTES );
      }
      catch { }  // пока мы игнорируем исключительные ситуации
    }    
    fileStream.Close();  // прибираем за собой (здесь должен быть блок finally)
}