Лучшее место для перевода в рабочее состояние нового окна в Образцовом Представлении ViewModel

Как говорит @MFisherKDX, проверьте возвращаемое значение scanf. Со страницы руководства scanf :

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

Значение EOF возвращается, если достигнут конец ввода перед первым успешным преобразованием или ошибкой сопоставления. EOF также возвращается, если происходит ошибка чтения, и в этом случае устанавливается индикатор ошибки для потока (см. Ferror (3)), и устанавливается errno, обозначающий ошибку.

blockquote>

Таким образом, захват возвращаемого значения scanf в переменной int и последующее сравнение этой переменной с 1 (в вашем случае, потому что вы пытаетесь только прочитать 1 элемент) должны сказать вам, если scanf успешно прочитал целочисленное значение.

Однако, есть неприятная ловушка при использовании scanf, о которой вы должны знать. Если вы введете n в командной строке, scanf завершится с ошибкой и вернет 0, но также не будет использовать введенный вами ввод. Это означает, что при следующем вызове scanf он будет читать тот же ввод (введенный вами символ n) и снова потерпит неудачу. И это будет продолжаться независимо от того, сколько раз вы звоните scanf. Меня всегда удивляет, что преподаватели информатики продолжают преподавать scanf студентам, учитывая не только эту потенциальную ловушку, но и несколько других ловушек . Хотелось бы, чтобы у меня был никель на каждый час , который какой-то студент CS где-то потратил, пытаясь заставить scanf вести себя так, как подсказывает их интуиция. Я бы уже вышел на пенсию на своем частном острове. Но я отвлекся.

Одним из способов обойти эту конкретную ловушку является проверка, не удалось ли scanf, и если это так, преднамеренно потреблять и отбрасывать весь ввод от stdin до следующего символа новой строки или EOF, в зависимости от того, что наступит раньше.

Сначала давайте рассмотрим некоторый фиксированный код un , который вызывает бесконечный цикл, если вы введете нецелое число в качестве ввода:

// Typing the letter 'n' and hitting  here causes an infinite loop:
int num, status;
while (1) {
  printf("Enter a number: ");
  status = scanf("%d", &num);
  if (status == 1)
    printf("OK\n");
  else
    printf("Invalid number\n");
}

Приведенный выше код будет (после Вы вводите n и нажимаете ), входите в бесконечный цикл и просто начинаете извергать «Неверное число» снова и снова. Опять же, это потому, что введенное вами n никогда не удаляется из буфера ввода.

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

// Fixed. No more infinite loop.
int num, status;
while (1) {
  printf("Enter a number: ");
  status = scanf("%d", &num);
  if (status == 1)
    printf("OK\n");
  else {
    printf("Invalid number\n");
    // Consume the bad input, so it doesn't keep getting re-read by scanf
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF) ;
    if (ch == EOF) break;
  }
}

9
задан Steve Dunn 17 March 2009 в 06:21
поделиться

7 ответов

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

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

Задача может быть отменена или зафиксирована. По завершении выдает уведомление.

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

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

У меня есть реализация этого для Silverlight. См. http://www.nikhilk.net/ViewModel-Dialogs-Task-Pattern.aspx для получения дополнительной информации ... Я хотел бы услышать комментарии / дополнительные предложения по этому поводу.

2
ответ дан 3 November 2019 в 08:21
поделиться

В примере недвижимого имущества Саутриджа Jaime Rodriguez и Karl Shifflet, они создают окно в viewmodel, более конкретно в выполнить части связанной команды:

    protected void OnShowDetails ( object param ) 
    {
        // DetailsWindow window = new DetailsWindow();
        ListingDetailsWindow window = new ListingDetailsWindow();
        window.DataContext = new ListingDetailsViewModel ( param as Listing, this.CurrentProfile ) ; 
        ViewManager.Current.ShowWindow(window, true); 
    } 

Вот ссылка: http://blogs.msdn.com/jaimer/archive/2009/02/10/m-v-vm-training-day-sample-application-and-decks.aspx

Я предполагаю, что это не имеет большой проблемы. В конце концов, Viewmodel действует как 'связующее звено' между представлением и бизнес-слоем слоя/данных, так по моему скромному мнению, нормально быть связанным с Представлением (UI)...

1
ответ дан 3 November 2019 в 08:21
поделиться

Оникс (http://www.codeplex.com/wpfonyx) предоставит довольно хорошее решение для этого. Как пример, посмотрите на услуги ICommonDialogProvider, которые могут использоваться от ViewModel как это:

ICommonFileDialogProvider provider = this.View.GetService<ICommonDialogProvider>();
IOpenFileDialog openDialog = provider.CreateOpenFileDialog();
// configure the IOpenFileDialog here... removed for brevity
openDialog.ShowDialog();

Это является очень похожим на использование конкретного OpenFileDialog, но является полностью тестируемым. Для объема отделения Вас действительно нужно, была бы деталь реализации для Вас. Например, в Вашем случае можно хотеть сервис, который полностью скрывает то, что Вы используете диалоговое окно. Что-то вроде:

public interface IRemoveFiles
{
   string[] GetFilesToRemove();
}

IRemoveFiles removeFiles = this.View.GetService<IRemoveFiles>();
string[] files = removeFiles.GetFilesToRemove();

Затем необходимо удостовериться, что Представление имеет реализацию для услуг IRemoveFiles, для которых существует несколько опций, доступных Вам.

Оникс еще не готов к выпуску, но код является полностью рабочим и применимым по крайней мере как контрольная точка. Я надеюсь выпустить, стабилизируют интерфейс V1 очень вскоре и выпустит, как только у нас есть достойная документация и образцы.

1
ответ дан 3 November 2019 в 08:21
поделиться

Я столкнулся с этой проблемой с MVVM также. Моя первая мысль состоит в том, чтобы попытаться найти способ не использовать диалоговое окно. Используя WPF намного легче придумать дождевик способ сделать вещи, чем с диалоговым окном.

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

Так, как простой пример при необходимости в пользователе для подтверждения удаления, ViewModel мог бы назвать DialogHelper. ConfirmDeletion (), который возвратил бы булевскую переменную того, сказал ли пользователь да или нет. Фактический показ диалогового окна был бы сделан в классе Помощника.

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

Я соглашаюсь, что это не самое гладкое соответствие с остальной частью MVVM, но я еще не нашел лучших примеров.

0
ответ дан 3 November 2019 в 08:21
поделиться

Я должен был бы сказать, Сервисы являются способом пойти сюда.

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

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

0
ответ дан 3 November 2019 в 08:21
поделиться

Для Диалоговых окон этого вида. Я определяю его как вложенный класс FindFilesCommand. Если основное диалоговое окно использовало среди многих команд, я определяю его в модуле, доступном для тех команд, и имею команду, настраивают диалоговое окно соответственно.

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

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

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

Снова в нескольких экземплярах, что диалоговое окно полезно для нескольких команд, я определяю его в модуле, характерном для всех них. Однако в моем программном обеспечении, возможно, 1 из 20 диалоговых окон похож на это. Так как основным исключением является файл, открываются/сохраняют диалоговое окно. Если бы диалоговое окно используется десятками команд затем, я пошел бы полным путем определения интерфейса, создания формы для реализации того интерфейса и регистрации той формы.

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

-1
ответ дан 3 November 2019 в 08:21
поделиться

То, что мы делаем, похоже на то, что описано здесь: http://www.codeproject.com/KB/WPF/DialogBehavior.aspx?msg=3439968#xx3439968xx

ViewModel имеет свойство, которое называется ConfirmDeletionViewModel. Как только я устанавливаю свойство, поведение открывает диалоговое окно (модальное или нет) и использует ConfirmDeletionViewModel. Кроме того, я передаю делегат, который выполняется, когда пользователь хочет закрыть диалоговое окно. По сути, это делегат, который устанавливает для свойства ConfirmDeletionViewModel значение null.

0
ответ дан 3 November 2019 в 08:21
поделиться
Другие вопросы по тегам:

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