Проблема с WPF и MVVM - PullRequest
       45

Проблема с WPF и MVVM

1 голос
/ 20 ноября 2010

, если попытаетесь внедрить мой первый MVVM в приложение WPF.У меня есть старое приложение, основанное на winforms, и я хочу использовать свою логику (класс) из этого проекта.

У меня есть Model, она состоит из следующих классов:

public class FriendData
{
//...
}

public class PingData
{
//...
}

public class PokecAccount : INotifyPropertyChanged, IDataErrorInfo
{
//...
}


public class Rp :INotifyPropertyChanged, IDataErrorInfo
{
//...
}


public class JsonUser:INotifyPropertyChanged
{
//...
}

И класса обслуживания, который отправляетHTTP GET и POST-запрос на сервере, этот класс реализует этот интерфейс:

interface IPokecService
{
    bool LogOn(string nick, string password);
    bool LogOff();
    JsonUser CreateJsonUser(string nick);
    void Ping();
    void IbRp();
    bool SendRp(Rp rp);
    Rp LoadRp();
}


public class PokecService:IPokec
{
 public PokecAccount account;
 public PingData pingData;

 //impelent interface IPokec

}

Я пытаюсь использовать DelegateCommand из WPF Model-View-ViewModel Toolkit 0.1.

С View У меня возникли проблемы.Но моя проблема в том, как «обернуть» методы из класса PokecService во ViewModel.

Пример с методом LogOn.

Сначала я создаю View.

StartUpWindow.xaml

    <StackPanel Grid.Row="1" Margin="12,12,12,12">
        <Label Name="lbAzetID" Content="AzetID" Style="{StaticResource lb1}"></Label>
        <TextBox Name="tbAzetID" Style="{StaticResource tb1}">
            <TextBox.Text>
                <Binding Path="AzetId" Mode="OneWayToSource" UpdateSourceTrigger="PropertyChanged">
                </Binding>
            </TextBox.Text>
        </TextBox>
        <Label Name="lbRegistration" Content="Registrácia" Style="{StaticResource lb1}">
            <Label.ToolTip>
                <StackPanel>
                    <TextBlock FontWeight="Bold">Registrácia</TextBlock>
                    <TextBlock>Nemáte vlástené AzetID, registrujte sa tu!</TextBlock>
                </StackPanel>
            </Label.ToolTip>
        </Label>
        <Label Name="lbPassword" Content="Heslo" Style="{StaticResource lb1}" ></Label>
        <TextBox Name="tbPassword" Style="{StaticResource tb1}">
            <TextBox.Text>
                <Binding Path="Password" Mode="OneWayToSource" UpdateSourceTrigger="PropertyChanged">
                </Binding>
            </TextBox.Text>
        </TextBox>
        <Label Name="lbForgetPassword" Content="Zabudli ste heslo?" Style="{StaticResource lb1}">
            <Label.ToolTip>
                <StackPanel>
                    <TextBlock FontWeight="Bold">Zabudli ste svoje heslo?</TextBlock>
                    <TextBlock>Nechajte si ho zaslať na Váš email.</TextBlock>
                </StackPanel>
            </Label.ToolTip>
        </Label>
    </StackPanel>
    <Button Name="LogOn"
            Command="{Binding LogOnCommand}"
            Content="Prihlásiť" 
            Width="100" 
            Height="25" 
            VerticalAlignment="Center"
            Grid.Row="2" />

Он состоит всего из 2 текстовых полей и одной кнопки, я привязываю кнопку запятую к свойству ViewModel.

VieModel StartUpViewModel.cs

В этом классе я хочу обернуть методы из класса PokecService в DelegateCommand и связать их с элементами управления пользовательского интерфейса.

public class StartUpViewModel
{

    private string _name = "KecMessanger";
    private string _password = "KecMessanger";
    private PokecService _pokecService;

    public StartUpViewModel()
    {
        _pokecService=new PokecService();
    }

    DelegateCommand _logOnCommand;

    public ICommand LogOnCommand
    {
        get
        {
            if(_logOnCommand==null)
            {
                _logOnCommand=new DelegateCommand(LogOn,CanLogOn);
            }
            return _logOnCommand;
        }
    }

    private void LogOn()
    {
        //In this method I need to call method LogOn from calss PokecService _pokecService.LogOn(_name,_password)          
        //if loging is success I need create another window - view and close this window
        //somehing like this:
        if (_pokecService.LogOn(_name, _password))
        {
            var newViewWindow = new AnotherView();
            //close StartUpView (its typeof window) but I don’t know how
            AnotherView.Show();
        }           
    }

    private bool CanLogOn()
    {
        return true;
    }
}

Мои вопросы:

  1. Я могу связывать элементы управления пользовательского интерфейса из свойств ViewModel, это не проблема.Это хороший способ "обернуть" методы из моего класса PokecService во ViewModel с DelegateCommad?

  2. Хорошо ли создать новое окно / View в ViewModel?Как закрыть реальное представление (окно) в ViewModel?

  3. Какое решение для этой проблемы наиболее подходит?

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

Спасибо за любой аванс.Извините за мой английский.

1 Ответ

1 голос
/ 20 ноября 2010
  1. Команды для связи между view и viewmodel в MVVM. Чтобы абстрагировать PokecService от ViewModel, я бы посоветовал вам использовать Dependency Injection (я сам использую MEF ).
  2. Я бы снабдил представление инъекцией зависимостей, чтобы класс был легче тестируемым. При необходимости создайте интерфейс, чтобы вы могли заменить фактическую реализацию класса обслуживания, не меняя тип везде.
  3. используйте контейнер DI.

Примечание: я использую WAF в качестве фреймворка MVVM вместе с MEF, и он работает как шарм.

Краткий пример:

[Export(typeof(IService))]
public class Service : IService
{
}

public interface IService
{
  void Method();
}

[Export]
public class Consumer
{
  private readonly IService _Service;

  [ImportingConstructor]
  public Consumer(IService service)
  {
    ser = service;
  }


  public void DoStuff()
  {
    //stuff
    _Service.Method();
  }
}

В методе запуска (т. Е. Application.OnStartup):

var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()); //insert the assembly defining the mentioned classes above
var container = new CompositionContainer(catalog);
container.ComposeParts(this);

Consumer c = container.GetExportedValue<Consumer>();
c.DoStuff();
...