在 UserControl WPF MVVM caliburn 内的 UserControls 之间切换

问题描述

我需要通过单击按钮从一个用户控件导航到另一个用户控件,并且我使用了两种不同的方法

enter image description here

方法 1:我有一个带有一些按钮的主窗口,这些按钮将使用导航控制器选择我的“父”用户控件视图模型。

    public NavigationController(MainWindowviewmodel viewmodel)
    {
        this.viewmodel = viewmodel;
    }

    public void Execute(object parameter)
    {
        string par = parameter.ToString();

        switch (par)
        {
            case "0":
                viewmodel.Selectedviewmodel = new viewmodel1();
                break;

            case "1":
                viewmodel.Selectedviewmodel = new viewmodel2();
                break;
        }
    }

XAML 端 (...)

  <Button Command="{Binding NavigationController}" CommandParameter="1" />
  <ContentControl Content="{Binding Selectedviewmodel}" />

到目前为止一切顺利,我相信这是一个很好的策略。 但是对于方法 2,我选择了正确的“父”用户控件,按钮单击以不同的方式绑定: XAML

    <Button cal:Message.Attach="ShowUserControl3()"/>

虚拟机

    public object SelectedActionviewmodel
    {
        get => _selectedActionviewmodel;
        set
        {
            _selectedActionviewmodel = value;
        }
    }

    public void ShowUserControl3()
    {
        _selectedActionviewmodel = new VMusercontrol3();
        OnPropertyChanged(nameof(SelectedActionviewmodel));
    }

第二种方法效果很好..在我第一次或第二次单击按钮时。之后,OnPropertyChanged 继续传递 null 并且不再选择正确的用户控件。我在这里错过了什么?

额外问题:如何从 UserControl4 中选择 UserControl3?

编辑:所有用户控件都继承自 Baseviewmodel,这就是奇怪的地方,因为 propertyChanged 为 null

public class Baseviewmodel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public event EventHandler ClosingRequest;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
        }
    }
}

解决方法

我希望我正确理解了您的问题。实现此目的的更简单方法是使用 Caliburn Micro 的内置支持。例如,将您的外壳视图模型修改为

public class ShellViewModel:Conductor<object>  // Replace object with your base viewmodel if any
{

        private UserControl1ViewModel _uc1Instance;
        public UserControl1ViewModel UC1Instance => _uc1Instance ?? (_uc1Instance = new UserControl1ViewModel());

        private UserControl2ViewModel _uc2Instance;
        public UserControl2ViewModel UC2Instance => _uc2Instance ?? (_uc2Instance = new UserControl2ViewModel());


        public void ActivateUserControl1()
        {
            ActivateItem(UC1Instance);
        }

        public void ActivateUserControl2()
        {
            ActivateItem(UC2Instance);
        }
}

来自 Caliburn Micro 的 Conductor<T> 类使您能够在只有一个活动的情况下处理多个屏幕(视图)。您现在可以将视图更改为

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <StackPanel Orientation="Vertical">
            <Button x:Name="ActivateUserControl1" Content="Show UC 1"/>
            <Button x:Name="ActivateUserControl2" Content="Show UC 2"/>
        </StackPanel>

        <ContentControl Grid.Column="1" x:Name="ActiveItem"/>
    </Grid>

可以在您的 UserControl1 和 UserControl2 中重复相同的过程,以实现设置 UserControl3 和 UserControl4 的 Options。

关于您的第二个问题,即关于 UserControl3 和 UserControl4 之间的通信,您可以使用 EventAggregators

您可以在 here 中找到 EventAggregator 的示例。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...