it-swarm.com.ru

WPF-MVVM: Настройка фокуса управления пользовательским интерфейсом из ViewModel

Что является хорошей практикой установки фокуса управления в архитектуре MVVM. 

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

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

Какая лучшая практика? 

42
Sonic Soul

Используйте IsFocused Attached Property, как предложено в ответе здесь: Установить фокус на текстовое поле в WPF из модели представления (C #)

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

27
Snarfblatt

Если вы используете Caliburn.Micro, вот сервис, который я создал, чтобы установить для Фокуса любой элемент управления в представлении, унаследованном от Screen.

Примечание:Это будет работать только в том случае, если вы используете Caliburn.Micro для своей инфраструктуры MVVM.

public static class FocusManager
{
    public static bool SetFocus(this IViewAware screen ,Expression<Func<object>> propertyExpression)
    {
        return SetFocus(screen ,propertyExpression.GetMemberInfo().Name);
    }

    public static bool SetFocus(this IViewAware screen ,string property)
    {
        Contract.Requires(property != null ,"Property cannot be null.");
        var view = screen.GetView() as UserControl;
        if ( view != null )
        {
            var control = FindChild(view ,property);
            bool focus = control != null && control.Focus();
            return focus;
        }
        return false;
    }

    private static FrameworkElement FindChild(UIElement parent ,string childName)
    {
        // Confirm parent and childName are valid. 
        if ( parent == null || string.IsNullOrWhiteSpace(childName) ) return null;

        FrameworkElement foundChild = null;

        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);

        for ( int i = 0; i < childrenCount; i++ )
        {
            FrameworkElement child = VisualTreeHelper.GetChild(parent ,i) as FrameworkElement;
            if ( child != null )
            {

                BindingExpression bindingExpression = GetBindingExpression(child);
                if ( child.Name == childName )
                {
                    foundChild = child;
                    break;
                }
                if ( bindingExpression != null )
                {
                    if ( bindingExpression.ResolvedSourcePropertyName == childName )
                    {
                        foundChild = child;
                        break;
                    }
                }
                foundChild = FindChild(child ,childName);
                if ( foundChild != null )
                {
                    if ( foundChild.Name == childName )
                        break;
                    BindingExpression foundChildBindingExpression = GetBindingExpression(foundChild);
                    if ( foundChildBindingExpression != null &&
                        foundChildBindingExpression.ResolvedSourcePropertyName == childName )
                        break;
                }

            }
        }

        return foundChild;
    }

    private static BindingExpression GetBindingExpression(FrameworkElement control)
    {
        if ( control == null ) return null;

        BindingExpression bindingExpression = null;
        var convention = ConventionManager.GetElementConvention(control.GetType());
        if ( convention != null )
        {
            var bindablePro = convention.GetBindableProperty(control);
            if ( bindablePro != null )
            {
                bindingExpression = control.GetBindingExpression(bindablePro);
            }
        }
        return bindingExpression;
    }
}

Как это использовать?

От вашей ViewModel, унаследованной от Caliburn.Micro.Screen или Caliburn.Micro.ViewAware

this.SetFocus(()=>ViewModelProperty); или this.SetFocus("Property");

Как это устроено?

Этот метод попытается найти элемент в дереве визуального представления, и фокус будет установлен на любой соответствующий элемент управления. Если такой элемент управления не найден, он будет использовать BindingConventions, используемую Caliburn.Micro.

Например,

Он будет искать Свойство в BindingExpression элемента управления . Для TextBox, он посмотрит, привязано ли это свойство к свойству Text, после чего будет установлен фокус.

12
Kishore Kumar

ViewModel бросает событие в View, сообщая, что действие было завершено, и View устанавливает фокус.

1
Alex Shtof

Вы можете ввести интерфейс для представления, чтобы ViewModel мог сказать представлению установить фокус. Пример приложения BookLibrary WPF Application Framework (WAF) показывает, как это сделать. Пожалуйста, посмотрите на BookListViewModel.

0
jbe

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

http://codenicely.blogspot.com/2012/01/how-to-set-textbox-focus-in-silverlight.html

0
Khalid Rafique