source

WPF-MVVM: ViewModel에서 UI 제어 포커스 설정

ittop 2023. 4. 12. 22:57
반응형

WPF-MVVM: ViewModel에서 UI 제어 포커스 설정

MVVM 아키텍처에서 제어 포커스를 설정하는 모범 사례는 무엇입니까?

View Model에서 필요할 때 포커스 변경을 트리거하는 속성을 사용하는 것이 제 생각입니다.또한 UI 컨트롤이 해당 속성을 바인드/리슨하여 변경 시 적절한 포커스를 설정할 수 있도록 합니다.

View Model이 특정 데이터를 로드하는 등의 특정 작업을 수행한 후 포커스를 적절하게 설정하려고 하기 때문에 View Model로 간주합니다.

베스트 프랙티스는 무엇입니까?

여기의 답변: 뷰 모델에서 WPF의 텍스트 상자에 포커스를 설정한다(C#)에서 제시된 대로 IsFocused Attached 속성을 사용합니다.

그런 다음 뷰 모델의 속성에 바인딩할 수 있습니다.

Caliburn을 사용하는 경우.Micro, Screen에서 상속된 보기에서 Focus를 컨트롤로 설정하기 위해 만든 서비스입니다.

참고: 이 기능은 캘리번을 사용하는 경우에만 작동합니다.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;
    }
}

사용법?

Caliburn에서 상속된 ViewModel에서.Micro.Screen 또는 Caliburn.Micro.ViewAware

this.SetFocus(()=>ViewModelProperty);또는this.SetFocus("Property");

어떻게 작동합니까?

이 메서드는 Visual Tree of View에서 요소를 검색하려고 하며 포커스가 일치하는 컨트롤로 설정됩니다.이러한 컨트롤을 찾을 수 없는 경우 Caliburn에서 사용하는 BindingConventions를 사용합니다.마이크로.

예전의 경우,

컨트롤의 BindingExpression에서 Property를 찾습니다.TextBox의 경우 이 속성이 Text 속성에 바인딩되어 있는지 확인한 후 포커스를 설정합니다.

ViewModel은 작업이 완료되었음을 알리는 이벤트를 View에 보내고 View는 포커스를 설정합니다.

언급URL : https://stackoverflow.com/questions/5340543/wpf-mvvm-setting-ui-control-focus-from-viewmodel

반응형