Как использовать шаблон ReactiveUI MessageBus для связи между двумя элементами UserControls? - PullRequest
0 голосов
/ 04 марта 2020

Я пытаюсь работать с платформой ReactiveUI в проекте wpf. Подробно я пытаюсь использовать шаблон MessageBus для связи между двумя разными моделями представления. В приведенном ниже упрощенном примере я пытаюсь обновить метку MainWindowView, когда нажимаю на вставку кнопки UserControl Button в MainWindowView. Нажатием кнопки управляет ReactiveUI BindCommand, который вызывает метод UserControlViewModel. Этот метод отправляет сообщение по механизму MessageBus ReactiveUI. MainWindowViewModel прослушивает сообщение и обновляет заголовок Label на 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");
        }
    }
}

I ожидал увидеть строку «TITOLO» в метке главного окна, но этого не произошло. Кто-то может объяснить мне, почему? Спасибо.

1 Ответ

1 голос
/ 04 марта 2020

Во-первых, я хочу отметить, что, хотя инфраструктура обеспечивает реализацию MessageBus, мы не рекомендуем ее использовать.

Я не вижу вас Регистрация источника сообщения где-либо в вашем примере.

Вам нужно позвонить куда-нибудь на RegisterMessageSource, что займет IObservable, и в этом случае я бы понял, что это должен быть ваш щелчок кнопки.

что-то вроде:

MessageBus.Current.RegisterMessageSource(ButtonTest.Events().Clicked)

Где Events().Clicked - это просто наблюдаемая оболочка для события нажатия кнопки.

На сайте ReactiveUI есть пример

...