Обработка состояния просмотра в Silverlight с помощью MVVM - PullRequest
7 голосов
/ 23 февраля 2010

Мне интересно знать, как вы, люди, там обрабатываете состояние просмотра в приложении Silverlight с шаблоном MVVM. Допустим, у меня есть простая маска поиска, которая асинхронно вызывает веб-сервис. Пока идет поиск, я бы хотел соответственно изменить графический интерфейс: - отключить кнопку поиска - Включить кнопку отмены - и т. д.

Используя wpf, я мог создать источник данных, который привязывается к какому-либо свойству в модели представления, а затем вносит изменения в графический интерфейс. Теперь, поскольку в Silverlight у меня нет датагергера, какой самый разумный способ добиться этого аналогично датгергеру (точный код, если возможно, в одном месте)?

( Я опубликовал аналогичный вопрос, но он был сформулирован плохо )

Ответы [ 4 ]

7 голосов
/ 23 февраля 2010

Мой стандартный способ сделать это - показать свойство ViewState из модели представления (обычно enum). Затем представление связывается со свойством и использует visualstatemanager для переключения в соответствующие визуальные состояния в зависимости от перечисления.

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

РЕДАКТИРОВАТЬ В ответ на комментарий

Во-первых, при работе с VisualStates используйте Blend (никто не должен заставлять писать столько XAML вручную). Я полагаю, что это даже на всех (большинство?) Подписок MSDN.

Использование визуальных состояний начинается с Диспетчер визуальных состояний

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="GroupOne">
        <VisualState x:Name="Normal"/>
        <VisualState x:Name="Searching"/>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Обычно вы добавляете это в layoutroot.

Диспетчер визуальных состояний состоит из коллекции StateGroups, которая, в свою очередь, состоит из коллекции VisualStates.

Группы поддерживают взаимоисключающие состояния организованно, поскольку вы можете иметь несколько активных визуальных состояний одновременно, но только одно состояние из каждой группы. Стандартный шаблон должен иметь пустое состояние, называемое чем-то вроде «Нормальное» или «По умолчанию», которое используется для отключения других состояний. Базовое состояние в основном.

В вашем случае у вас будет визуальное состояние "Поиск", которое будет содержать раскадровку, которая отключит различные кнопки, активирует анимацию занятости и т. Д.

0 голосов
/ 15 ноября 2011

1) Вы можете создать что-то вроде свойства IsEnabledSearch в модели представления и связать его со свойством Button IsEnabled или Visibility (вам потребуется конвертер Bool to Visibility). Создание новых визуальных состояний только для этого не очень эффективно, потому что ваши кнопки уже имеют все виды визуальных состояний внутри для поддержки этого поведения.

2) Фреймворк Jounce mvvm имеет очень хорошую реализацию для поддержки VisualStates из ViewModel; Jounce Visual State Manager

0 голосов
/ 16 марта 2011

Мое решение похоже на решение Грэма Брэдбери, НО я не использую DataStateSwitchBehavior, потому что если мой X-элемент управления находится внутри панели вкладок (или что-то похожее), а состояние изменяется, пока я на другой вкладке, тогда яполучить исключение («элемент» не найден ..).Исключение вызвано тем, что мой элемент управления X выгружен, пока я нахожусь на другой вкладке, и элементы, которые необходимо обновить, не найдены.

Итак, вот что я делаю:

В моей модели представления у меня есть свойство VisualState, которое отправляет уведомление при изменении состояния (я использую MVVM light toolkit ):

private string visualState = XVisualStates.InitialState;
    public string VisualState
    {
        get
        {
            return visualState;
        }

        set
        {
            visualState = value;
            Messenger.Default.Send(new XStateChangedMessage(value));
        }
    }

и в коде My view я подписываюсь на уведомление:

public partial class XControl : UserControl
{
    private string visualState = XVisualStates.InitialState;
    public XControl()
    {
        InitializeComponent();

        //go to state when view is loaded
        Loaded += (s, e) => ChangeState(); //every time a view is loaded go to current state

        //change visual state when a notification is received
        Messenger.Default.Register<XStateChangedMessage>(this,
            state =>
            {
                visualState = state.CurrentState; //save current state
                ChangeState();
            });
    }

    void ChangeState()
    {
        try
        {
            VisualStateManager.GoToState(this, visualState, true); //will throw an exception if current view is unloaded
        }
        catch
        {
            //NOTE: supress 'element' not found errors if user navigated to another view and state changes
        }
    }
}

и XStateChangedMessage - простой класс:

public class XStateChangedMessage 
{
    public string CurrentState { get; private set; }

    public XStateChangedMessage (string currentState)
    {
        CurrentState = currentState;
    }
}
0 голосов
/ 23 февраля 2010

Самый удобный способ - использовать BusyIndicator из Silverlight Toolkit Полагаю. Поскольку он маскирует всю область, к которой вы его применяете, все кнопки автоматически отключаются.

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

Затем вы просто привязали бы свойство IsBusy BusyIndicator к соответствующему свойству в вашей ViewModel, которое вы установили перед загрузкой и сбросили, когда закончите.

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