AvaloniaUI - 从后台代码访问 ViewModel

问题描述 投票:0回答:1

我正在尝试将旧的 WPF 应用程序移植到 Avalonia UI(Reactive MVVM),从而了解一些 Avalonia。在我的旧应用程序中,我使用了一种模式,在该模式中,我在视图的代码隐藏中包含事件代码(主要是按钮单击、下拉列表等)。因此,作为一个简化的示例,我的 WPF 应用程序中的模式如下所示(您可以跳过本节,因为它只是显示我的模式的基本 WPF 示例):

我的观点 - MainWindow.xaml:

  <Window x:Class="WpfTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBlock TextWrapping="Wrap" Text="{Binding Greeting}"/>
        <Button Content="Button" Click="Button_Click"/>
    </Grid>
</Window>

….视图背后的代码 – MainWindow.xaml.cs:

namespace WpfTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ViewModel myview = new ViewModel();
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = myview;  
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            myview.Greeting = "Hello";
        //…and here functions from other classes etc. are called
        }
    }
}

….最后是 ViewModel – ViewModel.cs:

namespace WpfTest
{
    internal class ViewModel:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChange(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
            }
        }


        private string _greeting;
        public string Greeting
        {
            get { return _greeting; }
            set
            {
                _greeting = value;
                RaisePropertyChange("Greeting");
            }
        }
    }
}

这种模式在创建相当复杂的应用程序时也能完美满足我的需求,即使我的能力有限,而且通常还允许我回收大量代码,因为模型仍然与程序的其余部分分离。 我知道 MVVM“纯粹主义者”会说视图背后的代码应该是空的,这也是我开始挣扎的地方,因为所有关于 Avalonia UI 的教程似乎都通过绑定到命令来完成我在 ViewModel 中所做的所有事情(事实上,在 ViewModel 之外似乎根本没有做太多事情)。我认为这将是最专业的做事方式,但是我想保留旧的 WPF 模式,因为它允许我回收大量代码。然而,我什至无法让上面的基本示例在 Avalonia MVVM 中工作。假设 ViewModel 看起来像这样:

namespace AvaloniaTest.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        private string? greeting;
        public string? Greeting
        {
            get => greeting;
            set => this.RaiseAndSetIfChanged(ref greeting, value);
        }
    }
}

以及View背后的代码(与WPF版本基本相同):

namespace AvaloniaTest.Views
{
    public partial class MainWindow : Window
    {
        MainWindowViewModel myview = new MainWindowViewModel();
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = myview;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            myview.Greeting = "Hello";
        }
    }
}

当我这样尝试时,当我单击按钮时,用户界面上没有任何反应。我想这与 App.axaml.cs 中已设置的 ViewModel 有关,并且我在代码中设置的 DataContext 不会对活动视图执行任何操作。但是,我还没有找到/理解如何从后面的代码访问实际的 ViewModel – 这有可能吗?

this问题中,答案再次是在ViewModel中创建ReactiveCommand。我发现的所有官方和非官方示例也仅使用 ViewModel 中的命令,但是文档提到也可以使用事件。

c# mvvm reactiveui avaloniaui
1个回答
0
投票

ViewModel 已经存在并保存在

DataContext
中。要将其用作 ViewModel,只需使用您喜欢的方法进行转换即可

DataContext as MainWindowViewModel

(MainWindowViewModel)DataContext
© www.soinside.com 2019 - 2024. All rights reserved.