Data Binding i StringFormat w Windows Phone 7

Tworząc aplikacje często spotykamy się z przypadkiem, kiedy chcemy stworzyć listę obiektów, które pobieramy z bazy danych. Często są to pojedyńcze listy, jak lista zakupów, lista kontaktów, lista państw itp. W WPF, korzystając z XAMLa możemy to zrobić poprzez mechanizm Data Binding, obszerny artykuł znajduje się na MSDNie Data Binding Overview

Co jeśli interesuje nas lista wieloelementowa, która zawierałaby wiele pól danych z jednego wiersza, oraz miała być ładnie sformatowana pod względem ustawienia elementów (coś a’la centrum SMS albo klient email) oraz formatu liczb? Do tego celu możemy użyć również mechanizmu Data Binding w celu połączenia danych, Grid w celu ustawienia danych, oraz StringFormat w celu ładnego przedstawienia.

Korzystamy z bazy danych umieszczonej w artykule Baza Danych w Windows Phone 7

W pliku MainPage.xaml.cs wystarczy, że podłączymy naszą bazę danych do kontekstu strony

[csharp]

public MainPage()
{
InitializeComponent();
// Set the data context of the listbox control to the sample data
this.DataContext = App.ViewModel;

}

[/csharp]

W ten sposób, cała strona podłączona jest już do źródła danych – ma tzw. kontekst, którego będzie mogła korzystać do pobierania, usuwania itp.  danych w bazie.

Teraz przechodzimy do najważniejszego pliku – MainPage.xaml. Tworzymy w tej chwili szablon każdego elementu (każdego wiersza tabeli), który będzie formatowany zawsze w ten sam sposób. Należy go umieścić w specjalnej przestrzeni – phone:PhoneApplicationPage.Resources

[xaml]

<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key=”EntriesListBoxItemTemplate”>
<Border
Background=”{StaticResource TransparentBrush}”
Padding=”20″>
<Grid HorizontalAlignment=”Stretch” Background=”{StaticResource TransparentBrush}”>

<Grid.ColumnDefinitions>
<ColumnDefinition Width=”100″ />
<ColumnDefinition Width=”100″ />
<ColumnDefinition Width=”80″ />
<ColumnDefinition Width=”80″ />
<ColumnDefinition Width=”*” />
</Grid.ColumnDefinitions>

<Grid.RowDefinitions>
<RowDefinition Height=”60″ />
<RowDefinition Height=”60″ />
</Grid.RowDefinitions>

<Grid Grid.Column=”0″ Grid.ColumnSpan=”1″ Grid.Row=”0″ Grid.RowSpan=”2″ Background=”{StaticResource PhoneAccentBrush}” Width=”110″ Height=”110″>
<TextBlock
x:Name=”theRectangle”
Text=”{Binding ItemFuelMill, StringFormat=\{0:0.00 \} }”
Foreground=”White”
FontSize=”{StaticResource PhoneFontSizeExtraLarge}”
VerticalAlignment=”Center” HorizontalAlignment=”Right”  Margin=”0,0,0,0″ />
</Grid>

<TextBlock
x:Name=”theTextBlock”
Text=”{Binding ItemDate, StringFormat=\{0: MMMM d\, yyyy\} }”
FontSize=”{StaticResource PhoneFontSizeLarge}”
Grid.Column=”1″ Grid.ColumnSpan=”4″
Grid.Row=”0″ Grid.RowSpan=”1″
VerticalAlignment=”Top” Margin=”0, 12, 0, 0″/>

<TextBlock
Text=”{Binding ItemDist, StringFormat=\{0:0.0 \}km }”
FontSize=”{StaticResource PhoneFontSizeSmall}”
Grid.Column=”1″ Grid.ColumnSpan=”1″
Grid.Row=”1″ Grid.RowSpan=”1″
VerticalAlignment=”Top” HorizontalAlignment=”Right” Margin=”0, 0, 0, 0″/>

<TextBlock
Text=”{Binding ItemRefuel, StringFormat=\{0:0.0 \}l }”
FontSize=”{StaticResource PhoneFontSizeSmall}”
Grid.Column=”2″ Grid.ColumnSpan=”1″
Grid.Row=”1″ Grid.RowSpan=”1″
VerticalAlignment=”Top” HorizontalAlignment=”Right” Margin=”0, 0, 0, 0″/>

<TextBlock
Text=”{Binding ItemFPrice, StringFormat=\{0:0.0 \}PLN }”
FontSize=”{StaticResource PhoneFontSizeSmall}”
Grid.Column=”3″ Grid.ColumnSpan=”1″
Grid.Row=”1″ Grid.RowSpan=”1″
VerticalAlignment=”Top” HorizontalAlignment=”Right” Margin=”0, 0, 0, 0″/>

</Grid>
</Border>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>

[/xaml]

DataTemplate to kontener, który będzie nam przechowywał szablon “jedego wiesza z tabeli”, nazwaliśmy go EntriesListBoxItemTemplate. Kontrolka Grid służy nam do umiejscowienia wszystkich elementów, które mają znaleźć się na liście, textblock to kontrolka, która będzie nam wyświetlać tekst. Cała magia Data Bindingu i StringFormatu odbywa się tutaj:

[xaml]

Text=”{Binding ItemRefuel, StringFormat=\{0:0.0 \}l }”

[/xaml]

Ta linijka oznacza mniej więcej: kiedy będziesz przerabiał każdy wiesz, weź z wiersza wartość elementu ItemRefuel, oraz nadaj mu format {0:0.0}l  – czyli jeśli będziemy mieć element o wartości 7.53, kontrolka wyświetli nam 7.5l (l tutaj po prostu oznaczają litry).

Bardzo ważne w tym przypadku są tzw. escape charactery, które powiedzą mechanizmowi, że nawiasy nie należą do Bindingu, lecz do właściwości StringFormat. Należy zaznaczyć, że operacja ta ma na celu tylko wyświetlać dane, a nie udostępniać do modyfikacji. Z tego powodu działa tu tryb OneWay – czyli “tylko pobieraj, nie wysyłaj do bazy niczego”, toteż możemy sobie pozwolić na takie modyfikacje.

 

Co do StringFormat działającego w trybie TwoWay, istnieje również alternatywa wspomniana w artykule z MSDN – stworzenie własnego konwertera – klasy, która będzie implementowała interfejs “IValueConverter”, przez to funkcję Convert (oraz ConvertBack, kiedy stosujemy Binding z opcją TwoWay). Bardzo dobry i obszerny przykład przedstawiam poniżej:

Data Binding and StringFormat in Silverlight « Matt Duffield.