重新排列Caliburn Micro中的父子激活顺序

时间:2015-01-16 18:47:52

标签: caliburn.micro

在我的视图模型中覆盖OnActivate()时,我需要调用GetView()来聚焦元素。在我之前激活我的视图后执行此操作时,它很好。但是当我称之为第一次激活时,它就失败了。

我能够通过在ConductorBaseWithActiveItem.ChangeActiveItem中交换几行来使其工作。原文如下:

protected virtual void ChangeActiveItem(T newItem, bool closePrevious) {
    ScreenExtensions.TryDeactivate(activeItem, closePrevious);
    newItem = EnsureItem(newItem);

    if(IsActive)
        ScreenExtensions.TryActivate(newItem);

    activeItem = newItem;
    NotifyOfPropertyChange("ActiveItem");
    OnActivationProcessed(activeItem, true);
}

以及我的更改:

protected virtual void ChangeActiveItem(T newItem, bool closePrevious) {
    ScreenExtensions.TryDeactivate(activeItem, closePrevious);

    newItem = EnsureItem(newItem);

    activeItem = newItem;
    NotifyOfPropertyChange("ActiveItem");

    if (IsActive)
        ScreenExtensions.TryActivate(newItem);

    OnActivationProcessed(activeItem, true);
}

这似乎有效。通知“ActiveItem”已更改会触发加载和缓存视图的代码。然后ScreenExtensions.TryActivate调用我的OnActivate覆盖。

问题:我没有注意到这样做有什么问题,但我很好奇是否有人比我知道这个改变会产生什么影响更好?

谢谢!

1 个答案:

答案 0 :(得分:1)

你可以尝试的一件事就是重写Caliburn的OnViewAttached方法并尝试将其集中在那里。话虽这么说,在MVVM中,焦点更多的是关注点,所以如果可能的话,应该将逻辑从ViewModel移动到View。

您可以解决此问题的一种方法是创建附加行为(您需要引用Microsoft.Expression.Interactions程序集):

public class FocusWhenVisibleBehavior : Behavior<FrameworkElement>
{
    protected override void OnAttached()
    {
        this.AssociatedObject.Loaded += this.Loaded;
        this.AssociatedObject.IsVisibleChanged += this.VisibleChanged;
    }

    protected override void OnDetaching()
    {
        this.AssociatedObject.Loaded -= this.Loaded;
        this.AssociatedObject.IsVisibleChanged -= this.VisibleChanged;
    }

    private void Loaded(object sender, RoutedEventArgs e)
    {
        this.TryFocus();
    }

    private void VisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        this.TryFocus();
    }

    private void TryFocus()
    {
        if (this.AssociatedObject.IsLoaded && this.AssociatedObject.IsVisible)
        {
            // Focus the control
            this.AssociatedObject.Focus();
        }
    }
}

并将该行为附加到您想要关注的任何控件上:

<Button>
    <i:Interaction.Behaviors>
        <b:FocusWhenVisibleBehavior/>
    </i:Interaction.Behaviors>
</Button>