Где в коде и как я должен говорить текстовое поле для отображения временного сообщения о загрузке при использовании MVVM? - PullRequest
3 голосов
/ 17 мая 2011

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

У меня асинхронный поиск работает нормально, но я 'Я новичок в WPF и MVVM.Раньше у меня не было должного разделения моего пользовательского интерфейса и модели, и поэтому было легко указать текстовым полям отображать «Запрос ...», пока фактические данные не были доступны.

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

Допустимо ли (с точки зрения MVVM), чтобы кнопка пользовательского интерфейса обновляла различные текстовые поля пользовательского интерфейса, говоря «Запрос... "внутри своего собственного события click (наряду с вызовом метода ViewModel, который в конечном итоге обновит свойства, с которыми связаны эти текстовые поля, которые затем должны заменить их фактическими данными)?

Если нет, где -should-эта логика пошла.(Я также знаю, что команды лучше, чем события onClick, но, пожалуйста, по одной за раз :))

Вот что я сейчас думаю:

class MainWindow
{
     private ViewModel _viewModel;

     doStuffButton_Click(object sender, RoutedEventArgs e)
     {
         textBox1.Text = "Querying..."
         textBox2.Text = "Querying..."
         // ... and so on in a foreach looop probably.

         _viewModel.asyncGoAndLookupStuff(); // starts a Task that
         // updates properties that the textBoxes are bound to
         // and fires the appropriate PropertyChanged events.
     }
}

Это хорошая практика?Если нет, как я должен получить такую ​​функциональность в ViewModel?У меня была попытка, и я столкнулся с серьезными проблемами, устанавливая свойства ViewModel для различных строк, в то же время все еще будучи в состоянии установить для них соответствующие (не строковые) значения из Модели при их обновлении.Может ли это быть решено с помощью ValueConverter (и нулевых значений)?Я действительно понятия не имею, как это сделать, но я пока мало смотрел на конвертеры.

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

РЕДАКТИРОВАТЬ:

Я не думал, что это будет уместно, но из ответов ниже это может быть.Внизу в модели у меня есть что-то похожее (немного больше / сложнее)

class DataItem
{
    // assume a ctor to set it up here.
    public int SmallNumber { get; private set; }
    public int BigNumber { get; private set;}
}

class Model
{
    public DataItem Foo;
    public DataItem Bar;
}

, и текстовые поля (в настоящее время) все связаны с такими вещами, как ViewModel.Model.Foo.SmallNumber или ViewModel.Model.Bar.BigNumber.

Действительно ли мне нужно создавать отдельные свойства в ViewModel для каждого подэлемента модели (например, ViewModel.FooSmallNumber как строковое свойство), чтобы они могли всебыть типами строк?Я хотел бы сохранить эту относительно прямую привязку непосредственно к модели, если это возможно, но все же иногда текстовые поля отображают полезные строки.(В настоящее время я не могу полагаться на то, что свойства Модели являются нулевыми, когда они запрашивают, они могут содержать устаревшую информацию ... Я мог бы изменить ее, чтобы очистить их, я думаю.)

Ответы [ 3 ]

2 голосов
/ 18 мая 2011

Если вы запрашиваете только один раз в начале, вы можете установить значение по умолчанию свойства Text следующим образом:
<TextBox Text="{Binding MyProperty, TargetNullValue="Querying...", FallbackValue="Querying..."}" />

Если вам нужен текст, чтобы вернуться к 'Запросу ...'при следующем запросе установите стиль текстового поля для всех затронутых текстовых полей с помощью триггера, который устанавливает текст, как только для некоторого логического значения (IsQuerying) в вашей виртуальной машине установлено значение true.Это перезапишет вашу привязку, если она не установлена ​​на TwoWay (и даже тогда я не уверен ...), поэтому, возможно, установка другого свойства - это путь (например, IsEnabled или Opacity).

    <Style x:Key="QueryingStyle" TargetType="{x:Type TextBox}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ElementName = ThisVrEditorView, Path=DataContext.IsQuerying}">
                <Setter Property="Text" Value="Querying..."/>   
                <Setter Property="IsEnabled" Value="False"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
2 голосов
/ 17 мая 2011

Ваша модель представления не должна знать о ваших элементах управления.Поэтому он не должен обновлять какие-либо из ваших свойств элемента управления.Вот как вы изменяете текст при выполнении запросов:

Создайте свойство зависимости string в вашей модели представления и привяжите его к тексту вашего первого текстового поля.Измените эту строку перед асинхронной загрузкой и после завершения асинхронного метода.

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

Наконец, следующий шаблон MVVM не относитсябудучи осторожным, речь идет об абсолютном разделении логики и представления.Задайте себе вопрос: «Если я изменю свое представление (переименовав элемент управления, удалив определенные детали и т. Д.), Повлияет ли это на мою модель представления? Если ответ« да », значит, в вашей системе тесно связаны детали.

1 голос
/ 17 мая 2011

Вы можете и должны делать все это в своей виртуальной машине.

Вы добавляете строковое свойство Item1 (с уведомлением об изменении) к виртуальной машине, и вы просто устанавливаете его как «Запрос ...» при запуске.После завершения асинхронного метода используйте Dispatcher.Invoke (или ThreadingContext), чтобы скопировать новые данные в свойства.

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