MVVM загружают данные во время или после конструкции ViewModel?

После проверки и до того, как INSERT проверяет, существует ли имя пользователя, с помощью mysqli (процедурный). Это работает:

//check if username already exists
       include 'phpscript/connect.php'; //connect to your database

       $sql = "SELECT username FROM users WHERE username = '$username'";
       $result = $conn->query($sql);

       if($result->num_rows > 0) {
           $usernameErr =  "username already taken"; //takes'em back to form
       } else { // go on to INSERT new record
26
задан mkmurray 28 March 2010 в 03:53
поделиться

5 ответов

Для событий вы должны использовать EventToCommand в MVVM Light Toolkit. Используя это, вы можете привязать любое событие любого элемента пользовательского интерфейса к relaycommand. Проверьте его статью о EventToCommand в

http://blog.galasoft.ch/archive/2009/11/05/mvvm-light-toolkit-v3-alpha-2-eventtocommand-behavior. aspx

Загрузите образец и посмотрите. Это великолепно. Тогда вам не понадобится какой-либо код. Пример выглядит следующим образом:

<Page x:Class="cubic.cats.Wpf.Views.SplashScreenView"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
      xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
    Title="SplashScreenPage">

    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <cmd:EventToCommand Command="{Binding LoadedCommand}" />
        </i:EventTrigger>        
    </i:Interaction.Triggers>

    <Grid>
        <Label Content="This is test page" />
    </Grid>
</Page>

и режим просмотра может быть таким

 public class SplashScreenViewModel : ViewModelBase
    {
        public RelayCommand LoadedCommand
        {
            get;
            private set;
        }

        /// <summary>
        /// Initializes a new instance of the SplashScreenViewModel class.
        /// </summary>
        public SplashScreenViewModel()
        {
            LoadedCommand = new RelayCommand(() =>
            {
                string a = "put a break point here to see that it gets called after the view as been loaded";
            });
        }
    }

, если вы хотите, чтобы модель представления имела EventArgs, вы можете просто установить PassEventArgsToCommand на true:

<i:Interaction.Triggers>
            <i:EventTrigger EventName="Loaded">
                <cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding LoadedCommand}" />
  </i:EventTrigger>        
</i:Interaction.Triggers>

и модель вида будет похожа на

public class SplashScreenViewModel : ViewModelBase
{
    public RelayCommand<MouseEventArgs> LoadedCommand
    {
        get;
        private set;
    }

    /// <summary>
    /// Initializes a new instance of the SplashScreenViewModel class.
    /// </summary>
    public SplashScreenViewModel()
    {
        LoadedCommand = new RelayCommand<MouseEventArgs>(e =>
        {
            var a = e.WhateverParameters....;
        });
    }

}
24
ответ дан Filburt 28 November 2019 в 07:50
поделиться

Следующее решение похоже на уже предоставленное и принятое, но оно использует не команду в модели представления для загрузки данных, а «нормальный метод». Я думаю, что команды больше подходят для действий пользователя (команды могут быть доступны и недоступны во время выполнения), поэтому используют обычный вызов метода, но также устанавливают триггер взаимодействия в представлении.

Я предлагаю это: создать класс модели представления. Создайте класс модели представления в xaml представления, создав его внутри свойства DataContext.

Реализуйте метод для загрузки данных в вашу модель представления, например, LoadData. Настройте представление так, чтобы этот метод вызывался при загрузке представления. Это делается с помощью триггера взаимодействия в вашем представлении, который связан с методом в модели представления (необходимы ссылки на «Microsoft.Expression.Interactions» и «System.Windows.Interactivity»):

View ( xaml):

<Window x:Class="MyWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test" 
    xmlns:viewModel="clr-namespace:ViewModels"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"            
    >
<Window.DataContext>
    <viewModel:ExampleViewModel/>
</Window.DataContext>
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <ei:CallMethodAction TargetObject="{Binding}" MethodName="LoadData"/>
    </i:EventTrigger>
</i:Interaction.Triggers>   

Это вызовет метод LoadData в ViewModel во время выполнения, когда загружено представление. Здесь вы загружаете свои данные.

public class ExampleViewModel
{
    /// <summary>
    /// Constructor.
    /// </summary>
    public ExampleViewModel()
    {
        // Do NOT do complex stuff here
    }


    public void LoadData()
    {
        // Make a call to the repository class here
        // to set properties of your view model
    }

Если метод в хранилище является асинхронным, вы также можете сделать метод LoadData асинхронным, но это не требуется в каждом случае.

Кстати, вообще я бы не стал загружать данные в конструктор модели представления. В приведенном выше примере конструктор (без параметров) модели представления вызывается, когда дизайнер отображает ваше представление. Выполнение сложных вещей может привести к ошибкам в конструкторе при отображении вашего представления (по той же причине, по которой я не буду делать сложные вещи в конструкторе представлений).

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

3
ответ дан Martin 28 November 2019 в 07:50
поделиться

Я решил просто связать XAML, декларативно связанный с обработчиком события Loaded в программном коде View, который, в свою очередь, просто вызвал метод объекта ViewModel через корневой элемент View UserControl DataContext.

Это было довольно простое, прямое и чистое решение. Думаю, я надеялся найти способ связать событие Loaded с объектом ViewModel таким же декларативным способом, каким вы можете использовать ICommands в XAML.

Возможно, я дал Клинджеру официальный ответ, но он оставил комментарий на мой вопрос, а не ответ. Поэтому я, по крайней мере, дал ему один комментарий к нему.

1
ответ дан mkmurray 28 November 2019 в 07:50
поделиться

У меня была такая же проблема при работе с сообщениями между родительским окном и дочерним окном. Просто измените порядок создания моделей представлений в вашем классе ViewModelLocator. Убедитесь, что все модели представлений, которые зависят от сообщения, созданы до модели представления, которая отправляет сообщение.

Например, в конструкторе вашего класса ViewModelLocator:

public ViewModelLocator()
{
    if (s_messageReceiverVm == null)
    {
        s_messageReceiverVm = new MessageReceiverVM();
    }

    if (s_messageSenderVm == null)
    {
        s_messageSenderVm = new MessageSenderVM();
    }
}
0
ответ дан bugged87 28 November 2019 в 07:50
поделиться

Хорошо, тогда. : -)

Вы можете привязать к методу в ViewModel, используя поведение.

Вот ссылка, которая поможет вам в этом. http://expressionblend.codeplex.com/

2
ответ дан 28 November 2019 в 07:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: