Опубликован: 02.08.2013 | Уровень: для всех | Доступ: платный
Самостоятельная работа 6:

Использование шаблона проектирования MVVM

< Лекция 15 || Самостоятельная работа 6: 12345 || Лекция 18 >

Здесь всё готово к привязке данных. В списке, который определен в коде, присутствует шаблон данных, содержащий три элемента:

Item – текстовый блок, содержит название элемента (Name), использует одностороннюю привязку данных (OneWay), в процессе работы с приложением не меняется.

Count – текстовое поле, в которое пользователю нужно вводить сведения о собранных элементах. Для его привязки к источнику данных (Count) используется двусторонняя (TwoWay) привязка, для ввода данных в это поле используется цифровая экранная клавиатура (InputScope="Number").

Check – текстовый блок, привязан к источнику данных (Count), то есть, к тому же, что и текстовое поле, используется для проверки того, что данные, введенные в текстовое поле были переданы в модель и обновили её состояние. После ввода данных в текстовое поле здесь отображается введенное в него число. Здесь используется односторонняя привязка.

В Листинге 23.4 приведен код файла LevelView.xaml, представления, которое используется для ввода и отображения сведений о том, завершен ли уровень.

<UserControl x:Class="sdkMVVMCS.View.LevelView"
    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"

    xmlns:src="clr-namespace:sdkMVVMCS.View"             

    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <UserControl.Resources>
        <src:BoolOpposite x:Key="BoolOpposite"/>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">
        <ListBox ItemsSource="{Binding}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="200"/>
                            <ColumnDefinition Width="80"/>
                            <ColumnDefinition Width="100"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock x:Name="Level" Text="{Binding Path=Name, Mode=OneWay}" Grid.Column="0" 
HorizontalAlignment="Left" VerticalAlignment="Center"/>
                        <CheckBox x:Name="Completed" IsChecked="{Binding Path=Completed, Mode=TwoWay}" Grid.Column="1" H
orizontalAlignment="Center" IsEnabled="{Binding Path=Completed, Converter={StaticResource BoolOpposite}}"/>
                        <TextBlock x:Name="Check" Text="{Binding Path=Completed, Mode=OneWay}" Grid.Column="2" 
HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>
Листинг 23.4. Код файла LevelView.xaml

Здесь так же есть несколько полей, в объявлении привязок данных присутствуют некоторые особенности:

Level – текстовый блок, содержит название уровня (Name), использует одностороннюю привязку данных (OneWay), в процессе работы с приложением не меняется.

Check – текстовый блок, использует одностороннюю привязку к свойству Completed, применяется для контроля правильности работы системы двусторонней привязки.

Completed – элемент управления Checkbox (флаг), его свойство IsChecked, определяющее то, установлен флаг или снят (то есть, интерпретируется ли его состояние как "истина", или "ложь"), привязано к свойству Completed (оно используется для хранения данных о том, завершен уровень или нет) с помощью двусторонней привязки данных. По умолчанию это свойство устанавливается в значение false, получая такое значение в свойство IsChecked, элемент управления выводится с неустановленным флагом. При установке флага мы не только хотим передать новое значение в модель, но и модифицировать свойство IsEnabled того же самого элемента. Если флаг не установлен (уровень не пройден), это свойство должно быть установлено в значение true – то есть, с флагом можно взаимодействовать и устанавливать его. А если флаг установлен – уровень пройден, его нужно заблокировать, запретив изменения и установив в false его свойство IsEnabled. Можно заметить, что если флаг не установлен (хранит значение false), он должен быть доступен для редактирования (IsEnabled равняется true), если флаг установлен (хранит true), он должен быть заблокирован (IsEnabled равняется false). Для того, чтобы получить подобную логику, можно воспользоваться конвертером значений. Конвертеры – это классы, реализующие интерфейс IValueConverter.

Конвертер BoolOpposite добавлен в качестве ресурса в XAML-файле LevelView.xaml. Его класс определен в файле LevelView.xaml.cs, Листинг 12.5, у него есть два метода – Convert, он преобразует данные при передаче из источника (модели) в приёмник (свойство элемента управления CheckBox) и ConvertBack – данные преобразуются при передаче из приёмника в источник, то есть, выполняет обратное преобразование. В данном случае преобразование логического значения источника, к которому привязано свойство логического типа, заключается в инверсии этого значения.

using System;
using System.Windows.Controls;
using System.Globalization;

namespace sdkMVVMCS.View
{
    public partial class LevelView : UserControl
    {
        public LevelView()
        {
            InitializeComponent();
        }
    }

   // Конвертер значеий для управления возможностью редактировать поле Completed
    // Если флаг не установлен, то есть, имеет значение False, 
свойство IsCompleted устанавливается в True
    //Если установлен - то есть имеет значение True, 
IsEnabled устанавливается в значение False и поле больше нельзя редактировать
   public class BoolOpposite : System.Windows.Data.IValueConverter
    {
       
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool b = (bool)value;
            return !b;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string s = value as string;
            bool b;

            if (bool.TryParse(s, out b))
            {
                return !b;
            }
            return false;
        }
   }
}
Листинг 23.5. Код файла LevelView.xaml.cs
< Лекция 15 || Самостоятельная работа 6: 12345 || Лекция 18 >
Вася Пупкин
Вася Пупкин
Россия, с. Оймякон
антон Антонкин
антон Антонкин
Россия