wpf 使用CommunityToolkit.Mvvm和依赖注入更新视图模型的属性

inn6fuwd  于 2023-01-14  发布在  其他
关注(0)|答案(1)|浏览(766)

我正在尝试实现一个简单的WPF应用程序,在主窗口中有两个嵌套的UserControl,每个UserControl都有自己的视图模型。一个视图模型实现一个命令,允许用户选择目录。当在第一个视图模型中选择了一个文件夹时,它应该向所有其他注册的视图模型发送一条消息。所以我们有三个视图,三个视图模型(包括MainViewModel)和依赖容器。虽然我实现了IRECievier,但ReceiverVM不更新它的属性。
以下是我的视图模型,为了方便起见,我将它们放在同一个文件中:

namespace MessagingReproduction;

public partial class MainViewModel : ObservableRecipient
{

}

public partial class SenderViewModel : ObservableRecipient
{
    
    private string selectedDirectory;
    public string SelectedDirectory
    {
        get => selectedDirectory;
        set
        {
            var oldValue = selectedDirectory;
            SetProperty(ref selectedDirectory, value);
            Messenger.Send<PropertyChangedMessage<string>>(new PropertyChangedMessage<string>(this, nameof(SelectedDirectory), oldValue, selectedDirectory));
        }
    }

    // simulate a FolderDialog
    [RelayCommand]
    private void SelectDirectory()
        => this.SelectedDirectory = "C:";
}

public partial class ReceiverViewModel : ObservableRecipient, IRecipient<PropertyChangedMessage<string>>
{
    [ObservableProperty]
    private string selectedDirectory;

    public void Receive(PropertyChangedMessage<string> message)
    {
        selectedDirectory = message.NewValue;
    }
}

我的接收器视图.xaml:

<Grid>
        <TextBlock Text="{Binding SelectedDirectory, UpdateSourceTrigger=PropertyChanged}"
                   Width="120" Height="22"/>
    </Grid>

我的发件人视图.xaml:

<StackPanel>
        <Button Command="{Binding SelectDirectoryCommand}"
                Width="120" Height="22"/>
        <TextBlock Text="{Binding SelectedDirectory, UpdateSourceTrigger=PropertyChanged}"
                   Width="120" Height="22"/>
    </StackPanel>

主窗口:

<StackPanel>
        <local:SenderView DockPanel.Dock="Top"/>
        <local:ReceiverView DockPanel.Dock="Bottom"/>
    </StackPanel>

依赖项注入的设置见App.xaml.cs:

public partial class App : Application
    {
        public App()
        {
            Services = ConfigureServices();
            InitializeComponent();
        }

        public new static App Current => (App)Application.Current;
        public IServiceProvider Services { get; }
        private static IServiceProvider ConfigureServices()
        {
            var services = new ServiceCollection();
            services.AddTransient<MainViewModel>();
            services.AddTransient<SenderViewModel>();
            services.AddTransient<ReceiverViewModel>();

            return services.BuildServiceProvider();
        }
    }

在每个视图中设置数据上下文,如下所示:

public ReceiverView()
        {
            InitializeComponent();
            DataContext = App.Current.Services.GetService<ReceiverViewModel>();
        }

尽管实现了IRrecipient,但是视图模型并不通信。注意,除了主窗口之外,我的视图都是用户控件。

nhhxz33t

nhhxz33t1#

我只是学习使用MVVM工具包自己,但它似乎你没有实现任何消息,也没有注册您的接收器视图模型作为一个收件人的消息。
首先,创建消息:

public class ChangeDirectoryMessage : ValueChangedMessage<string>
{
    public ChangeDirectoryMessage(string newDirectory) : base(newDirectory)
    {        
    }
}

然后,在接收类中注册消息:

public class ReceiverViewModel : ObservableObject, IRecipient<ChangeDirectoryMessage>
{
    [ObservableProperty]
    private string selectedDirectory;

    public ReceiverViewModel()
    {
        WeakReferenceMessenger.Default.Register<ChangeDirectoryMessage>(this);
    }

    public void Receive(ChangeDirectoryMessage message)
    {
        selectedDirectory = message.NewValue;
    }
}

最后,当所选目录发生更改时,从任何地方发送消息:

WeakReferenceMessenger.Default.Send(new ChangeDirectoryMessage(selectedDirectory));

文档中有一个很好的示例说明如何使用此信使:
https://learn.microsoft.com/en-us/windows/communitytoolkit/mvvm/messenger

相关问题