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

ОГЛАВЛЕНИЕ

Счетчик

Страница Сount схожа со страницей Search. Мы начнем с добавления двух пространств имен, которые необходимо расположить в верхней части страницы Xaml,

xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"
xmlns:charting="clr-namespace:Microsoft.Windows.Controls.DataVisualization.Charting;assembly=Microsoft.Windows.Controls.DataVisualization"           

Это требует добавления другого пространства имен, на этот раз Microsoft.Windows.ControlsDataVisualization.dll, который также прилагается к инструментарию.

Пользовательский интерфейс состоит из графика и кнопки возврата (Return), поэтому для этого я создал две строки в табличной сетке в соотношении 6 к 1,

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
      <RowDefinition Height="6*" />
      <RowDefinition Height="1*" />
    </Grid.RowDefinitions>

В пределах данной сетки расположен объект Chart. Я назвал его letterFreqChart и данное название может быть использовано программным путем. График имеет три критических привязки:

  • IndependentValueBinding
  • DependendentValueBinding
  • ItemSource

В нашем случае мы установим первые два в Xaml, а третью программным путем, получив ItemSoure посредством метода UtilizeState.

Измерение частоты

Одним непростым фактором тут является то, что график сопоставляет независимое значение (в нашем случае - букву из алфавита) с зависимым значением (количеством слов, начинающихся с данной буквы). Хотя у нас и имеется набор слов, у нас нет данной информации и у нас тем более нет ее в отдельном объекте. Поэтому мы должны немного  переждать и создать новый объект, который предоставит нам ItemSource для данного графика.

public class Freq
{
  public int Count { get; set; }
  public char Letter { get; set; }
 
  public static List<Freq> Tally( List<string> words )
  {
    string prevChar = "a";
    int counter = 0;
    List<Freq> freqs = new List<Freq>();
    foreach ( string w in words )
    {
      if ( w.ToLower().StartsWith( prevChar.ToLower() ) )
        counter++;
      else
      {
        freqs.Add( new Freq(){ Letter=prevChar.ToLower()[0] ,Count=counter });
        prevChar = w.Substring( 0, 1 );
        counter = 1;
      }
      // z
      freqs.Add( new Freq() { Letter = prevChar.ToLower()[0], Count = counter } );        
    }
    return freqs;
  }
}

Frequency предоставляет два свойства - Count и Letter, а также один статический метод Tally. Вы передаете список строки в Tally и он возвращает список объектов Freq , каждый из которых содержит букву и количество слов в оригинальном списке, которые начинаются с данной буквы. Поэтому, если вы передадите в Tally список данных слов: “also, author, away, both, bottom, change” , то вы получите список из трех элементов Freq, первый из них будет иметь свойство Count со значением 3 и Letter со значением ‘a’. Второй будет иметь свойство Count со значением 2 и Letter со значением ‘b’, а у третьего Count будет равно 1 и Letter со значением ‘c’.

Вот полный Xaml-код страницы Count,

<UserControl x:Class="PageSwitching.Count"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Microsoft.Windows.Controls;
   assembly=Microsoft.Windows.Controls"
xmlns:charting="clr-  
  namespace:Microsoft.Windows.Controls.DataVisualization.Charting;
    assembly=Microsoft.Windows.Controls.DataVisualization"            
Width="400" Height="300">
  <Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
      <RowDefinition Height="6*" />
      <RowDefinition Height="1*" />
    </Grid.RowDefinitions>
    <charting:Chart x:Name="letterFreqChart" >
      <charting:Chart.Series>
        <charting:ColumnSeries
          Title="Count"
          IndependentValueBinding="{Binding Letter}"
          DependentValueBinding="{Binding Count}" />
      </charting:Chart.Series>
    </charting:Chart>
    <Button x:Name="returnBtn" Content="Return"
    FontSize="18" Grid.Row="1" Height="30" Width="100"/>
  </Grid>
</UserControl>

Вы можете заметить, что Independent Value (независимое значение) привязывается к свойству Letter , а Dependent Value (зависимое значением) - к свойству Count, явно объекту типа Freq, хотя мы еще не предоставили такой объект - это произойдет в коде. А вот код для Count.xaml.cs

using System.Collections.Generic;
using System.Windows.Controls;
 
namespace PageSwitching
{
  public partial class Count : UserControl, ISwitchable
  {
    private List<Freq> freqs;
    private List<string> sortedWords;
 
    public Count()
    {
      InitializeComponent();
      Loaded += new System.Windows.RoutedEventHandler( Count_Loaded );
    }
 
    void Count_Loaded( object sender, System.Windows.RoutedEventArgs e )
    {
      returnBtn.Click += new System.Windows.RoutedEventHandler( returnBtn_Click );
      Microsoft.Windows.Controls.DataVisualization.Charting.ColumnSeries cs = letterFreqChart.Series[0] as
        Microsoft.Windows.Controls.DataVisualization.Charting.ColumnSeries;
      cs.ItemsSource = freqs;
    }
 
    void returnBtn_Click( object sender, System.Windows.RoutedEventArgs e )
    {
      Switcher.Switch( new PageSwitcher() );
    }
 
    public void UtilizeState( object state )
    {
      sortedWords = state as List<string>;
      freqs = Freq.Tally( sortedWords );
    }
  }
}

Мы начнем с объявления двух наборов - список объектов Freq и список строк. В важном методе UtilzieState sortedWords заполняется из состояния и затем вызывается Tally с sortedWords в качестве входного параметра, а список объектов Freq -- в качестве возвращаемого значения.

Вторая и третья строки обработчика события Loaded назначает List<Freqs> в качестве источника данных СolumnSeries ItemSource,

Microsoft.Windows.Controls.DataVisualization.Charting.ColumnSeries cs = letterFreqChart.Series[0] as
   Microsoft.Windows.Controls.DataVisualization.Charting.ColumnSeries;
 cs.ItemsSource = freqs;

Вторая строка не совсем понятна, потому давайте ее разберем,

letterFreqChart.Series[0]  // найдите первый элемент в списке для нашего графика 

// преобразуйте его в тип Column

as Microsoft.Windows.Controls.DataVisualization.Charting.ColumnSeries 

//назначение его ссылки на объект данного типа

Microsoft.Windows.Controls.DataVisualization.Charting.ColumnSeries cs =

Как только мы совершили данное присвоение, у нас будет ColumnSeries и теперь мы можем назначить ItemSource. А вот как будет выглядеть график,

Рисунок 8-10. Заполненный график

Скачать исходники примеров

Jesse Liberty
Источник