Библиотека CSF MVVM
calabonga
22.08.2010
Программы NET
Silverlight 4: MVVM + ListBox или демонстрация библиотеки CSF-MVVM
Очень часто приходится писать небольшие программки (Silverlight), например, чтобы протестировать ту или иную функцию. Так вот, каждый раз проводить подготовку для того чтобы хотя бы просто запустить проект дело не быстрое. Что такое “подготовка”? Например, написать класс, который будет базовым для всех ViewModel’s и будет реализовывать интерфейс INotifyPropertyChanged. Или написать DelegateCommand<T>, который реализует ICommand интерфейс. Или еще какие-нибудь полезные и правильные вещи. Много и часто пользовался MVVM Light Toolkit, но часто бывает что и эта библиотечка большая и требует немного больше времени, чем можно себе позволить.
Именно от того, что лень – двигатель прогресса, как-то сама собой написалась простенька и легковесная библиотека для разработки Silverlight-приложение с использованием MVVM шаблона программирования. Размер библиотеки (Calabonga.Silverlight.Framework.dll) всего 12 Кб, ну просто очень легкая!
Итак, теперь примеры использования.
Допустим у нас есть класс:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
Очень простой класс. А еще у нас есть поставленная задача, использую MVVM сделать какую-нибудь выборку из ListBox в “куда-нибудь”. Очень простая и довольно тупая задача. Ну что ж, как говорят французы - “се ля ви” (такова жизнь). Чего не придумаешь лишь бы показать что может делать библиотека.
Создадим класс PersonsViewModel и унаследуем его от ViewModelBase, что уже содержится в CFF-MVVM. Прилепим к этому классу некоторые команды и свойства:
public class PersonsViewModel : ViewModelBase {
#region конструктор
public PersonsViewModel()
{
if (!DesignerProperties.IsInDesignTool)
{
GeneratePersonList();
}
}
#endregion
#region скрытые методы
private void GeneratePersonList()
{
List<Person> list = new List<Person>()
{
new Person(){ FirstName="Владлен", LastName="Суходрищев", Age=32},
new Person(){ FirstName="Афонасий", LastName="Пискоструев", Age=22},
new Person(){ FirstName="Антон", LastName="Застратов", Age=36}
};
PersonList = new ObservableCollection<Person>(list);
}
#endregion
#region команда RemoveSelectionCommand
/// <summary>
///Команда RemoveSelectionCommand
/// </summary>
public DelegateCommand<ListBox> RemoveSelectionCommand
{
get
{
return new DelegateCommand<ListBox>((e) => this.RemoveSelectionCommandExecute(e));
}
}
/// <summary>
///Процедура выполняет команды RemoveSelectionCommand
/// </summary>
private void RemoveSelectionCommandExecute(ListBox list)
{
// выполнение команды ShowSelection
MessageBox.Show("Отменен выбор: " + list.SelectedItems.Count.ToString() + " элемента(ов)");
list.SelectedItem = null;
this.SelectedList.Clear();
OnPropertyChanged(SelectedListPropertyName);
}
#endregion // end команда RemoveSelectionCommand
#region команда UpdateSelectionCommand
/// <summary>
///Команда UpdateSelectionCommand
/// </summary>
public DelegateCommand<SelectionChangedEventArgs> UpdateSelectionCommand
{
get
{
return new DelegateCommand<SelectionChangedEventArgs>((e) => this.UpdateSelectionCommandExecute(e),
(e) => this.CanExecuteUpdateSelection(e));
}
}
/// <summary>
///Процедура выполняет команды UpdateSelectionCommand
/// </summary>
private void UpdateSelectionCommandExecute(SelectionChangedEventArgs e)
{
// выполнение команды UpdateSelection
foreach (Person person in e.AddedItems)
{
if (!this.SelectedList.Contains(person))
{
this.SelectedList.Add(person);
}
}
foreach (Personperson ine.RemovedItems)
{
this.SelectedList.Remove(person);
}
}
/// <summary>
///Свойство проверки возможности выполнения команды UpdateSelectionCommand()
/// </summary>
private boolCanExecuteUpdateSelection(SelectionChangedEventArgse)
{
// разрешен ли запуск команды
returne.AddedItems.Count > 0;
}
#endregion// end команда UpdateSelectionCommand
#regionсвойство PersonList
/// <summary>
///поле для хранения значений свойства<see cref="PersonList"/>
/// </summary>
privateObservableCollection<Person> personList = null;
/// <summary>
///наименование поля для свойства<see cref="PersonList"/>
/// </summary>
private const stringPersonListPropertyName = "PersonList";
/// <summary>
///описание.
/// </summary>
publicObservableCollection<Person> PersonList
{
get
{
returnpersonList;
}
set
{
personList = value;
OnPropertyChanged(PersonListPropertyName);
}
}
#endregionсвойство PersonList
#regionсвойство SelectedList
/// <summary>
///поле для хранения значений свойства<see cref="SelectedList"/>
/// </summary>
privateObservableCollection<Person> selectedPersons = newObservableCollection<Person>();
/// <summary>
///наименование поля для свойства<see cref="SelectedList"/>
/// </summary>
private const stringSelectedListPropertyName = "SelectedList";
/// <summary>
///описание.
/// </summary>
publicObservableCollection<Person> SelectedList
{
get
{
returnselectedPersons;
}
set
{
selectedPersons = value;
OnPropertyChanged(SelectedListPropertyName);
}
}
#endregionсвойство SelectedList
А также не помешает создать класс представления для нашего приложения, в котором будет два контрола типа ListBox. В одном можно будет выбирать Items, а в другом будет показываться выбор. Кажется всё просто, но тут возникает некоторая заминка, как обработать событие SelectionChanged, если в код-behind мы ничего не должны писать (так гласит основной принцип программирования по шаблону MVVM). Помощь в решении данной проблемы окажет прикольная штука EventToCommand из моей библиотеки:
1) подключаем необходимые namespace’ы:
xmlns:csf="clr-namespace:Calabonga.Silverlight.Framework;assembly=Calabonga.Silverlight.Framework"xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
2) теперь в самом ListBox подключаем:
<ListBox ItemsSource="{Binding Path=PersonList}"
Margin="12,0,244,6"
Background="#FFF4FFFF"
x:Name="list"
SelectionMode="Extended"
Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="5 0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}"
Margin="0 0 5 0" />
<TextBlock Text="{Binding Path=LastName}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Возраст:"
Margin="0 0 5 0" />
<TextBlock Text="{Binding Path=Age}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<csf:EventToCommand Command="{Binding Path=UpdateSelectionCommand}"
IsSendEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers> </ListBox>
Вот, собственно говоря, и всё.
Скачать демонстрационный проект
Скачать библиотеку (Текущая версия: 1.1.7)
Просмотрено раз:
2712
Комментарии