Проблема с WPF и MVVM
Если попытаться реализовать мой первый MVVM в приложении WPF. У меня есть старое приложение, основанное на winforms, и я хочу использовать свою логику (класс) из этого проекта.
У меня есть модель, она состоит из следующих классов:
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.
Сначала я создаю вид.
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;
}
}
Мои вопросы:
Я могу связать элементы управления пользовательского интерфейса из свойств ViewModel, это не проблема. Это хороший способ "обернуть" методы из моего класса PokecService во ViewModel с DelegateCommad?
Это хорошо, создать новое окно / View в ViewModel? Как я могу закрыть фактический вид (окно) в ViewModel?
Какое решение для этой проблемы наиболее подходит?
Я думаю, что мне нужно только обернуть мои методы с переменной DelegateCommand, и создать для этих свойств переменной, и эти свойства привязать к элементам управления пользовательского интерфейса, но я абсолютный новичок в MVVM. Я прочитал несколько статей, но они показывают только очень простую демонстрацию.
Спасибо за любое продвижение. Извините за мой английский.
1 ответ
- Команды создаются для связи между view и viewmodel в MVVM. Чтобы абстрагировать PokecService от ViewModel, я бы посоветовал вам использовать Dependency Injection (я сам использую MEF).
- Я бы снабдил представление инъекцией зависимостей, чтобы класс был легче тестируемым. При необходимости создайте интерфейс, чтобы вы могли заменить фактическую реализацию класса обслуживания, не меняя тип везде.
- используйте 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();