我正在尝试在wpf项目中使用ReactiveUI框架。详细地说,我尝试使用MessageBus模式在两个不同的视图模型之间进行通信。在下面的简化示例中,当我单击MainWindowView按钮insert into MainWindowView时,我尝试更新UserControl标签。按钮单击由调用UserControlViewModel方法的ReactiveUI BindCommand管理。该方法通过MessageBus ReactiveUI机制发送消息。MainWindowViewModel侦听消息并更新显示窗口标题的MainWindowView上的标签标题。我不知道为什么这不管用。
下面是代码:
MainWindowView (Xaml):
<rxui:ReactiveWindow x:Class="TestMessageBus.MainWindowView"
        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:TestMessageBus"
        xmlns:rxui="http://reactiveui.net"
        x:TypeArguments="local:MainWindowViewModel"             
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <Label x:Name="TitleLabel" HorizontalAlignment="Center"/>
        <local:UserControlView/>
    </StackPanel>
</rxui:ReactiveWindow>MainWindowView (代码隐藏):
namespace TestMessageBus
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindowView : ReactiveWindow<MainWindowViewModel>
    {
        public MainWindowView()
        {
            InitializeComponent();
            ViewModel = new MainWindowViewModel();
            this.WhenActivated(disposable =>
            {
                this.OneWayBind(ViewModel, vm => vm.Title, v => v.TitleLabel.Content)
                    .DisposeWith(disposable);
            });
        }
    }
}MainWindowViewModel:
namespace TestMessageBus
{
    public class MainWindowViewModel : ReactiveObject
    {
        public string Title { get; set; }
        public MainWindowViewModel()
        {
            MessageBus.Current.Listen<string>("Contract1").Subscribe(x => MessageSend(x));
        }
        private void MessageSend(string title)
        {
            Title = title;
        }
    }
}UserControlView (Xaml):
<rxui:ReactiveUserControl x:Class="TestMessageBus.UserControlView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TestMessageBus"
             xmlns:rxui="http://reactiveui.net"
             x:TypeArguments="local:UserControlViewModel" 
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="200">
    <Grid>
        <Button x:Name="ButtonTest">TEST</Button>
    </Grid>
</rxui:ReactiveUserControl>UserControlView (代码隐藏):
namespace TestMessageBus
{
    /// <summary>
    /// Interaction logic for UserControlView.xaml
    /// </summary>
    public partial class UserControlView : ReactiveUserControl<UserControlViewModel>
    {
        public UserControlView()
        {
            InitializeComponent();
            ViewModel = new UserControlViewModel();
            this.WhenActivated(disposable =>
            {
                this.BindCommand(ViewModel, vm => vm.ClickCommand, v => v.ButtonTest).DisposeWith(disposable);
            });
        }
    }
}UserControlViewModel:
namespace TestMessageBus
{
    public class UserControlViewModel: ReactiveObject
    {
        public ReactiveCommand<Unit, Unit> ClickCommand { get; set; }
        public UserControlViewModel()
        {
            ClickCommand = ReactiveCommand.Create(ClickButton);
        }
        private void ClickButton()
        {
            MessageBus.Current.SendMessage("TITOLO", "Contract1");
        }
    }
}我希望在MainWindow标签中看到"TITOLO“字符串,但这并没有发生。有人能解释一下为什么吗?谢谢。
发布于 2020-03-04 14:36:58
首先我想指出的是,即使框架提供了MessageBus实现,我们也不推荐使用它。
在您的示例中,我没有看到您注册消息源。
你应该有一个对RegisterMessageSource的调用,它接受一个IObservable,在这种情况下,我认为应该是你点击了按钮。
类似于:
MessageBus.Current.RegisterMessageSource(ButtonTest.Events().Clicked)其中Events().Clicked只是按钮单击事件的一个可观察的包装器。
在ReactiveUI Website上有一个例子
发布于 2020-10-24 07:21:39
这是一种潜在的方法,但我不确定它是否符合反应式UI的最佳实践。对我来说,问题是Subject把IObservable和IObserver搞得一团糟。
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Diagnostics;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading.Tasks;
namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        private static string GetSomeData() => "Hi";
        [TestMethod]
        public async Task TestMethod8()
        {
            var subject = new Subject<string>();
            //Create a class and inject the subject as IObserver
            new Publisher(subject);
            //Create a class and inject the subject as IObservable
            new Subscriber(subject);
            new Subscriber(subject);
            new Subscriber(subject);
            //Run the loop for 10 seconds
            await Task.Delay(10000);
        }
        class Publisher
        {
            public Publisher(IObserver<string> observer)
            {
                Task.Run(async () =>
                {
                    //Loop forever
                    while (true)
                    {
                        //Get some data, publish it with OnNext and wait 500 milliseconds
                        observer.OnNext(GetSomeData());
                        await Task.Delay(500);
                    }
                });
            }
        }
        class Subscriber
        {
            //Listen for OnNext and write to the debug window when it happens
            public Subscriber(IObservable<string> observable) => observable.Subscribe((s) => Debug.WriteLine(s));
        }
    }
}https://stackoverflow.com/questions/60516166
复制相似问题