MVVM с веб-сервисом - PullRequest
       4

MVVM с веб-сервисом

1 голос
/ 26 июня 2010

Я собираюсь сделать приложение wpf, используя MVVM (оно основано на http://www.codeproject.com/KB/WPF/MVVMQuickTutorial.aspx).

Это приложение будет подключаться к веб-сервису один раз в месяц.

На веб-сервисе у меня есть контракт

public class Student
{
        public string Name {get; set;}
        public int Score {get; set;}
        public DateTime TimeAdded {get; set;}
        public string Comment {get; set;}
}

В приложении WPF Добавление и удаление студентов сохраняются в формате xml.файл.

Так что в приложении wpf Student будет выглядеть примерно так:

public class Student
{
    public string Name {get; set;}
    public int Score {get; set;}
    public DateTime TimeAdded {get; set;}
    public string Comment {get; set;}

    public Student(string Name, int Score,
        DateTime TimeAdded, string Comment) {
        this.Name = Name;
        this.Score = Score;
        this.TimeAdded = TimeAdded;
        this.Comment = Comment;
    }
}

public class StudentsModel: ObservableCollection<Student>
{
    private static object _threadLock = new Object();
    private static StudentsModel current = null;

    public static StudentsModel Current {
        get {
            lock (_threadLock)
            if (current == null)
                current = new StudentsModel();

            return current;
        }
    }

    private StudentsModel() 
    {

        // Getting student s from xml
        }
    }

    public void AddAStudent(String Name,
        int Score, DateTime TimeAdded, string Comment) {
        Student aNewStudent = new Student(Name, Score,
            TimeAdded, Comment);
        Add(aNewStudent);
    }
}

Как соединить эти два класса?

Худшее, на мой взгляд, заключение - контракт Student с веб-сервисабудет использоваться в этом wpf-приложении для получения студентов из xml, в других приложениях набор данных будет получен из базы данных.

Я новичок в шаблонах проектирования, поэтому мне очень трудно: /

Пример: я нажимаю AddUser, и в приложении A он вызывает метод webservice, который добавляет пользователя в базу данных, в приложении B он добавляет пользователя в файл XML, а в приложении.Базовый класс - это контракты в веб-сервисе.

Следующее объяснение:

Первое приложение использует веб-сервис для сохранения данных в базе данных.Второе приложение никогда не сохраняет данные в формате xmls, и один раз в месяц пермиссия отправляет эти xmls в веб-сервис и конвертирует их в экземпляры студентов и сохраняет их в базе данных

Ответы [ 3 ]

7 голосов
/ 29 июня 2010

Из вашего вопроса очень непонятно, в чем проблема. Но, думаю, я мог бы обратиться к нескольким и показать вам способ их решения.

1) Основная проблема, которую я вижу в вашем проекте, состоит в том, что у вас есть два определения класса Student. Вы можете легко объединить их в одно определение. (Я просто покажу вам, как ...)

2) Очень неясно, хотите ли вы, чтобы ваш WPF клиент сохранял данные в Data Source (XML?) Или ваш Web Service должен это сделать. И если WPF клиент должен сохранить Student s, тогда зачем нужен Web Service?

3) У вас нет ViewModel определенного для Student класса, который в данном случае равен Model.

Я создал пример с 3 проектами.

1) WebService - Сервисный проект WCF

2) StudentLib - Проект библиотеки классов (где определен Student класс)

3) DesktopClient - Проект приложения WPF

Вот исходный код:

WebService.IStudentService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using StudentLib;

namespace WebService
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IStudentService" in both code and config file together.
    [ServiceContract]
    public interface IStudentService
    {
        [OperationContract]
        StudentLib.Student GetStudentById(Int32 id);

        [OperationContract]
        void AddStudent(StudentLib.Student student);
    }
}

WebService.StudentService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using StudentLib;

namespace WebService
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "StudentService" in code, svc and config file together.
    public class StudentService : IStudentService
    {
        public StudentLib.Student GetStudentById(int id)
        {
            return new StudentLib.Student() { Name = "John Doe", Score = 80, TimeAdded = DateTime.Now, Comment = "Average" };
        }

        public void AddStudent(StudentLib.Student student)
        {
            // Code to add student
        }
    }
}

WebService's Web.Config

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <bindings />
    <client />
    <services>
      <service name="WebService.StudentService" behaviorConfiguration="metaDataBehavior">
        <endpoint address="basic" binding="basicHttpBinding" contract="WebService.IStudentService" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metaDataBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

StudentLib.Student.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;

namespace StudentLib
{
    [DataContract]
    public class Student
    {
        [DataMember]
        public String Name { get; set; }

        [DataMember]
        public Int32 Score { get; set; }

        [DataMember]
        public DateTime TimeAdded { get; set; }

        [DataMember]
        public String Comment { get; set; }
    }
}

DesktopClient.StudentViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesktopClient
{
    class StudentViewModel
    {
        protected StudentLib.Student Student { get; set; }

        public StudentViewModel(StudentLib.Student student)
        {
            this.Student = student;
        }

        public String Name { get { return Student.Name; } }
        public Int32 Score { get { return Student.Score; } }
        public DateTime TimeAdded { get { return Student.TimeAdded; } }
        public String Comment { get { return Student.Comment; } }
    }
}

DesktopClient.MainWindow.xaml

<Window x:Class="DesktopClient.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="400"
        Height="300"
        Loaded="Window_Loaded">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TextBlock Grid.Column="0"
                   Grid.Row="0">Name :</TextBlock>
        <TextBlock Grid.Column="1"
                   Grid.Row="0"
                   Text="{Binding Name}"></TextBlock>
        <TextBlock Grid.Column="0"
                   Grid.Row="1">Score :</TextBlock>
        <TextBlock Grid.Column="1"
                   Grid.Row="1"
                   Text="{Binding Score}"></TextBlock>
        <TextBlock Grid.Column="0"
                   Grid.Row="2">Time Added :</TextBlock>
        <TextBlock Grid.Column="1"
                   Grid.Row="2"
                   Text="{Binding TimeAdded}"></TextBlock>
        <TextBlock Grid.Column="0"
                   Grid.Row="3">Comment :</TextBlock>
        <TextBlock Grid.Column="1"
                   Grid.Row="3"
                   Text="{Binding Comment}"></TextBlock>
    </Grid>
</Window>

DesktopClient.MainWindow.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DesktopClient.StudentService;
using StudentLib;

namespace DesktopClient
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            IStudentService client = new StudentServiceClient();

            Student student = client.GetStudentById(1);
            DataContext = new StudentViewModel(student);

            client.AddStudent(new StudentLib.Student() { Name = "Jane Doe", Score = 70, TimeAdded = DateTime.Now, Comment = "Average" });
        }
    }
}

Здесь решены все вышеперечисленные проблемы:

1) Класс Student определен в общей сборке (StudentLib), на которую ссылаются как WebService проект, так и DesktopClient проект. Таким образом, при добавлении Service Reference этот класс повторно используется генератором кода.

2) Я рекомендую, чтобы все операции с хранилищем выполнялись в Web Service, а приложение Client должно просто использовать Web Service для хранения данных.

3) StudentViewModel класс используется вместо Student класса для отображения данных в MainWindow.

0 голосов
/ 29 июня 2010

К счастью, классы уже «связаны», по крайней мере, в форме: поскольку ViewModel - это просто набор моделей.

В шаблоне MVVM вы захотите обработать свои функции привязки данныхв ViewModel.Это включает следующее:

  • Конструктор StudentModel (private StudentsModel() { ...) должен загрузить себя со всеми экземплярами Student.(В качестве альтернативы, вы можете использовать отдельную функцию Load () - что кажется наиболее логичным, если у вас также есть метод Save ().) Здесь вы, вероятно, читаете файл XML, используйте XmlSerializer для десериализации XML-данные в коллекцию студентов (возможно, List), затем добавьте их к себе, используя базовый конструктор (для всего списка) или Add () метод (oneза один раз, например, в цикле).
  • Вам понадобятся функции для добавления учеников в коллекцию, как в учебном примере.В настольном приложении вы можете вызвать функцию «Добавить» в веб-сервисе, и в случае успеха вы добавите ее в свою собственную коллекцию в памяти.Затем вам нужно решить, хотите ли вы немедленно сохранить (сериализованные) данные в XML-файл или сделать все это позже (например, при выгрузке объекта или вызове метода Save ()).
  • Вы, вероятно, хотите включить метод удаления объектов Student из коллекции.Здесь будут полезны открытые методы ObservableCollection, но вам может потребоваться / нужно больше логики, чем при выборе объекта (ов) для удаления.И снова, здесь вы должны уведомить веб-сервис об удаленных элементах и ​​знать, собираетесь ли вы сохранить изменения сразу или дождаться отдельного события.
  • Наследование от ObservableCollection мудро, так как это дает вам много магии, которая делает привязку динамической - я имею в виду, где пользовательский интерфейс обновляется по мере изменения данных.Если вы используете базовые методы Add (), Remove () и т. Д., Вы получаете преимущества IEnumerable , INotifyPropertyChanged и INotifyCollectionChanged .

Вы можете заметить, что я в основном упоминал сериализацию XML в приведенном выше объяснении, но для создания веб-службы с аналогичной функциональностью вы будете обмениваться такими идеями, как «сериализация XML и сохранение в файл» для ».сохранить изменения в вашей базе данных ".Шаблон тот же, просто фактические действия (реализация) разные.

Короче говоря, здесь ViewModel, где вы хотите реализовать все вещи, которые загружают и обрабатывают данные в памяти исохраняет его в файл, базу данных или веб-службу.

0 голосов
/ 27 июня 2010

Вы можете использовать следующую архитектуру.

1) Приложение WPF (приложение A & B) с app.config, который содержит URL-адрес веб-службы или путь к файлу XML

2) Business/ Уровень данных Создайте прокси-класс для URL-адреса веб-службы и создайте класс Student Model, который вы упомянули в своем посте.Измените метод Add для поддержки обеих функций.Вызовите метод Add в Webservice, если app.config имеет URL-адрес веб-службы (приложение A), или вызовите метод add для метода XML, если в appsetting есть путь к файлу XML (приложение B)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...