Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Создание проектов

Читайте также:
  1. I СОЗДАНИЕ ОРГАНИЗАЦИОННОЙ ДИАГРАММЫ
  2. I Создание рисунка в технике акварель
  3. II СОЗДАНИЕ ДИАГРАММ ДРУГИХ ТИПОВ
  4. II Создание пользовательской кисти
  5. III Технология использования градиента. Создание пользовательского градиента
  6. Intel и студенческие лаборатории проводят конкурс проектов приложений для Intel Atom
  7. IV. Разработка законопроектов

В первую очередь необходимо создать проекты будущего приложения. В простейшем случае это будут 3 сборки: WPF Application, Silverlight Application, а также Web Application для хостинга Silverlight приложения.

Окно создание проекта вызывается нажатием пункта меню File – New – Project:

Рисунок л.р. 6.1. Вызов окна создания проекта.

В появившемся окне необходимо перейти в раздел Other Project Types – Visual Studio Solutions и выбрать Blank Solution:

Рисунок л.р. 6.2. Создание пустого решения.

В созданное решение следует добавить Silverlight и WPF проекты, используя контекстное меню обозревателя решений:

Рисунок л.р. 6.3. Добавление проекта в решение.

Для добавления Silverlight приложения необходимо выбрать пункт Silverlight Application в разделе Visual C# – Silverlight:

Рисунок л.р. 6.4. Добавление Silverlight приложения.

В появившемся диалоговом окне следует подтвердить создание Web Application для размещения Silverlight приложения и выбрать версию Silverlight:

Рисунок л.р. 6.5. Задание параметров Silverlight приложения.

Аналогично необходимо добавить WPF приложение:

Рисунок л.р. 6.6. Добавление WPF приложения.

Вместе с проектами были автоматически созданы главные окна, MainWindow.xaml и MainPage.xml, для WPF и Silverlight соответственно. Так как эти сущности различны в двух версиях (в случае WPF это окно, в Silverlight – UserControl), их невозможно повторно использовать. Однако в них можно поместить приведенный в лекции #11 элемент управления ViewModelPresenter, который будет делегировать создание внутренней разметки представлению, соответствующему находящейся в DataContext модели представления.

MainWindow.xaml:

1: <Window x:Class="CrossPlatformApplication.MainWindow"

2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

4: xmlns:view="clr-namespace:CrossPlatformApplication"

5: Title="{Binding Title}" SizeToContent="WidthAndHeight">

6:

7: <view:ViewModelPresenter ViewModel="{Binding}" />

8: </Window>

MainPage.xaml:

1: <UserControl x:Class="SilverlightApplication.MainPage"

2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

4: xmlns:view="clr-namespace:CrossPlatformApplication">

5:

6: <view:ViewModelPresenter ViewModel="{Binding}" />

7: </UserControl>

Согласно принципам MVVM главному представлению приложения должна соответствовать модель представления. Для начала достаточно пустого класса, общего для WPF и Silverlight:

1: [Export]

2: [PartCreationPolicy(CreationPolicy.NonShared)]

3: [ExportMetadata(AopExtensions.AspectMetadata,

4: Aspects.NotifyPropertyChanged)]

5: public class MainViewModel: IEntitledViewModel

6: {

7: public string Title

8: {

9: get { return "Test Application"; }

10: }

11: }

Затем для корректного запуска приложения необходимо добавить логику инициализации IoC контейнера MEF и MVVM окружения, а также модифицировать логику отображения главных окон. Как в WPF, так и в Silverlight приложении модифицируется код App.xaml и App.xaml.cs.

App.xaml в WPF:

1: <Application x:Class="WpfApplication.App"

2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

4: <Application.Resources>

5:

6: </Application.Resources>

7: </Application>

App.xaml.cs в WPF:

1: public partial class App

2: {

3: #region Injected properties

4:

5: [Import]

6: public ChildViewManager ChildViewManager

7: { private get; set; }

8:

9: #endregion

10:

11: protected override void OnStartup(StartupEventArgs e)

12: {

13: base.OnStartup(e);

14:

15: // Create interception configuration

16: var cfg = new InterceptionConfiguration()

17:.AddAopInterception();

18:

19: var container = new CompositionContainer(

20: new InterceptingCatalog(new AggregateCatalog(

21: new DirectoryCatalog(".", "*.exe"),

22: new DirectoryCatalog(".", "*.dll")), cfg));

23:

24: var locator = new MefServiceLocator(container);

25: ServiceLocator.SetLocatorProvider(() => locator);

26: container.ComposeExportedValue<IServiceLocator>(locator);

27: container.ComposeParts(this);

28:

29: new MainWindow { DataContext =

30: locator.GetInstance<MainViewModel>() }.Show();

31: }

32: }

App.xaml в Silverlight:

1: <Application x:Class="SilverlightApplication.App"

2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

4: <Application.Resources>

5:

6: </Application.Resources>

7: </Application>

App.xaml.cs в Silverlight:

1: public partial class App

2: {

3: public App()

4: {

5: Startup += Application_Startup;

6: Exit += Application_Exit;

7: UnhandledException += Application_UnhandledException;

8:

9: InitializeComponent();

10: }

11:

12: #region Injected properties

13:

14: [Import]

15: public ChildViewManager ChildViewManager

16: { private get; set; }

17:

18: #endregion

19:

20: private void Application_Startup

21: (object sender, StartupEventArgs e)

22: {

23: // Create interception configuration

24: var cfg = new InterceptionConfiguration()

25:.AddAopInterception();

26:

27: var container = new CompositionContainer(

28: new InterceptingCatalog(

29: new DeploymentCatalog(), cfg));

30: var locator = new MefServiceLocator(container);

31: ServiceLocator.SetLocatorProvider(() => locator);

32: container.ComposeExportedValue<IServiceLocator>(locator);

33: container.ComposeParts(this);

34:

35: RootVisual = new MainPage

36: { DataContext = locator.GetInstance<MainViewModel>() };

37: }

38:

39: private void Application_Exit(object sender, EventArgs e)

40: {

41:

42: }

43:

44: private void Application_UnhandledException

46: (object sender, ApplicationUnhandledExceptionEventArgs e)

47: {

48: if (!System.Diagnostics.Debugger.IsAttached)

49: {

50: e.Handled = true;

51: Deployment.Current.Dispatcher.BeginInvoke(

52: delegate { ReportErrorToDOM(e); });

53: }

54: }

55:

56: private void ReportErrorToDOM

57: (ApplicationUnhandledExceptionEventArgs e)

44: {

45: try

46: {

47: string errorMsg = e.ExceptionObject.Message

48: + e.ExceptionObject.StackTrace;

49: errorMsg = errorMsg.Replace('"',

50: '\'').Replace("\r\n", @"\n");

51:

52: System.Windows.Browser.HtmlPage.Window.Eval(

53: "throw new Error(\"Unhandled Error in Silverlight Application "

54: + errorMsg + "\");");

55: }

56: catch (Exception)

57: {

58: }

59: }

60: }

Как видно из кода, главные окна приложения будут отображать представление MainView, соответствующее модели представления MainViewModel. Пусть это представление будет содержать простой текст «Hello world»:

1: <UserControl x:Class="CrossPlatformApplication.MainView"

2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

5: xmlns:mc

6: ="http://schemas.openxmlformats.org/markup-compatibility/2006"

7: mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">

8:

9: <Grid x:Name="LayoutRoot" Background="White" MinHeight="150"

10: MinWidth="200">

11: <TextBlock Text="Hello world"

12: HorizontalAlignment="Center"

13: VerticalAlignment="Center" />

14: </Grid>

15: </UserControl>

 

Естественно, как говорилось в лекции #12, необходимо создать представление в Silverlight проекте и добавить ссылку на него в WPF проект. Теперь оба приложения готовы к запуску и отображают на своем главном окне сообщение «Hello world».

Следующим этапом следует некоторое усложнение примера – размещенная на главном представлении кнопка будет отображать модальное дочернее окно, считывающее строку у пользователя. Введенные данные модифицируют исходный текст на главном представлении.

В первую очередь необходимо создать модель представления диалога, которая наследуется от введенного в лекции #14 класса ModalViewModelBase:

1: [Export]

2: [PartCreationPolicy(CreationPolicy.NonShared)]

3: [ExportMetadata(AopExtensions.AspectMetadata,

4: Aspects.NotifyPropertyChanged)]

5: public class TextInputModalChildViewModel:

6: ModalChildViewModelBase

7: {

8: public virtual string Text { get; set; }

9: }

Далее создается представление, содержащее поле ввода, привязанное к свойству Text:

1: <UserControl

2: x:Class="CrossPlatformApplication.TextInputModalChildView"

3: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

4: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

5: xmlns:i=

6: "http://schemas.microsoft.com/expression/2010/interactivity"

7: xmlns:ic=

8: "http://schemas.microsoft.com/expression/2010/interactions"

9: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

10: xmlns:mc=

11: "http://schemas.openxmlformats.org/markup-compatibility/2006"

12: mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">

13:

14: <StackPanel x:Name="LayoutRoot" Background="White">

15: <TextBlock Text="Введите новый текст" />

16: <TextBox Text="{Binding Text, Mode=TwoWay}" />

17: <StackPanel Orientation="Horizontal"

18: HorizontalAlignment="Right">

19: <Button Content="OK" Command="{Binding CloseCommand}"

20: Width="80" Height="30" Margin="6">

21: <i:Interaction.Triggers>

22: <i:EventTrigger EventName="Click">

23: <ic:ChangePropertyAction

24: PropertyName="ModalResult" Value="True"

25: TargetObject="{Binding}" />

26: </i:EventTrigger>

27: </i:Interaction.Triggers>

28: </Button>

29: <Button Content="Cancel"

30: Command="{Binding CloseCommand}" Width="80"

31: Height="30" Margin="6" />

32: </StackPanel>

33: </StackPanel>

34: </UserControl>

Здесь используется библиотека Expression Interactions, входящая в состав Microsoft Expression Blend 4, которая позволяет использовать кроссплатформенные Silverlight/WPF триггеры, схожие по функциональности с WPF триггерами, а также добавляют понятие поведения элемента управления, аналога которому в стандартной поставке WPF нет.

Далее, для работы с асинхронными моделями представления модальных дочерних окон удобно использовать библиотеку Reactive Extensions (Rx Framework):

1: public static class ObservableHelper

2: {

3: public static IObservable<EventPattern<EventArgs>>

4: ObserveClosed(this ICloseableViewModel childViewModel)

5: {

6: return Observable.FromEventPattern(

7: handler => childViewModel.Closed += handler,

8: handler => childViewModel.Closed -= handler);

9: }

10:

11: public static IObservable<T> SelectSender<T>

12: (this IObservable<EventPattern<EventArgs>> observable)

13: {

14: return observable.Select(ev => (T)ev.Sender);

15: }

16:

17: public static IObservable<T> WhereSucceeded<T>

18: (this IObservable<T> observable)

19: where T: IModalChildViewModel

20: {

21: return observable.Where(vm => vm.ModalResult.HasValue

22: && vm.ModalResult.Value);

23: }

24: }

 

1: public static class ViewModelExtension

2: {

3: /// <summary>

4: /// Resolves and shows Closeable View Model of

5: /// type <typeparamref name="T" />

6: /// </summary>

7: public static IObservable<T> ResolveAndShow<T>

8: (this IServiceLocator serviceLocator,

9: Action<T> prepareAction = null)

10: where T: ICloseableViewModel

11: {

12: var viewModel = serviceLocator.GetInstance<T>();

13:

14: if (prepareAction!= null)

15: {

16: prepareAction(viewModel);

17: }

18:

19: IObservable<T> result = Observable.FromEventPattern

20: (handler => viewModel.Closed += handler,

21: handler => viewModel.Closed -= handler)

22:.SelectSender<T>();

23:

24: viewModel.Show();

25:

26: return result;

27: }

28: }

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

Класс ViewModelExtension представляет метод, который одним вызовом разрешает закрываемую модель представления из IoC контейнера, показывает её и возвращает IObservable последовательность её закрытия.

Используя введенные сущности, в модели представления главного окна добавляется логика отображения диалога. Для видимого эффекта использования диалога введенный в окне текст заменяет приветственный текст по умолчанию:

1: [Export]

2: [PartCreationPolicy(CreationPolicy.NonShared)]

3: [ExportMetadata(AopExtensions.AspectMetadata,

4: Aspects.NotifyPropertyChanged)]

5: public class MainViewModel: EntitledViewModelBase

6: {

7: // Private fields

8: private string _text = "Hello world";

9:

10: public virtual string Text

11: {

12: get { return _text; }

13: protected set { _text = value; }

14: }

15:

16: #region Commands

17:

18: private ICommand _showTextInputCommand;

19:

20: public ICommand ShowTextInputCommand

21: {

22: get

23: {

24: return _showTextInputCommand??

25: (_showTextInputCommand =

26: new ActionCommand(ShowTextInput));

27: }

28: }

29:

30: #endregion

31:

32: #region Injected properties

33:

34: [Import]

35: public IServiceLocator ServiceLocator { private get; set; }

36:

37: #endregion

38:

39: public override string Title

40: {

41: get { return "Test Application"; }

42: }

43:

44: private void ShowTextInput()

45: {

46: ServiceLocator

47:.ResolveAndShow<TextInputModalChildViewModel>()

48:.WhereSucceeded()

49:.Subscribe(vm => Text = vm.Text);

50: }

51: }

Соответственно, также изменяется разметка представления главного окна:

1: <UserControl x:Class="CrossPlatformApplication.MainView"

2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

5: xmlns:mc=

6: "http://schemas.openxmlformats.org/markup-compatibility/2006"

7: mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">

8:

9: <Grid x:Name="LayoutRoot" Background="White"

10: MinHeight="150" MinWidth="200">

11: <TextBlock Text="{Binding Text}"

12: HorizontalAlignment="Center"

13: VerticalAlignment="Center" />

14: <Button Content="Изменить"

15: Command="{Binding ShowTextInputCommand}"

16: Width="80" Height="30"

17: HorizontalAlignment="Right"

18: VerticalAlignment="Bottom" Margin="6" />

19: </Grid>

20: </UserControl>

 


Дата добавления: 2015-08-13; просмотров: 60 | Нарушение авторских прав


Читайте в этой же книге: Задача 3. | Принцип инверсии зависимостей | Формы инверсии зависимостей | IoC контейнер | Сопоставление модели представления и представления | Реализация INotifyPropertyChanged средствами аспектно-ориентированного программирования | Краткие итоги | Понятие IChildViewModelManager | ChildViewManager | Реализация ChildViewModelBase |
<== предыдущая страница | следующая страница ==>
Реализация MessageViewModel| ОТ АВТОРА

mybiblioteka.su - 2015-2024 год. (0.039 сек.)