Nest реактивные пользовательские элементы управления wpf / pass ViewModel в пользовательский контроль - PullRequest
0 голосов
/ 30 октября 2019

В: Как я могу связать ViewModel с ReactiveUserControl? Или как вложить представления Reactiveui? Возможно, я что-то не так делаю, но не могу понять, что именно.

ReactiveUserControl

// MenuView.xaml
<reactiveui:ReactiveUserControl
       x:Class="Views.MenuView"
       xmlns:menuItems="clr-namespace:Model"    
    .... >
    <Menu x:Name="RootMenu"
          IsMainMenu="True">
        <Menu.Resources>
            <DataTemplate DataType="{x:Type menuItems:DialogItem}">
                <TextBlock Text="{Binding Description}" />
            </DataTemplate>
        </Menu.Resources>
    </Menu>
</reactiveui:ReactiveUserControl>
// MenuView.xaml.cs
namespace Views
{
    public partial class MenuView : ReactiveUserControl<MenuViewModel>
    {
        public MenuView()
        {
            InitializeComponent();

            this.WhenActivated(disposables =>
            {
                this.OneWayBind(ViewModel,
                    vm => vm.MenuItems,
                    view => view.RootMenu.ItemsSource
                ).DisposeWith(disposables);
            });
        }
    }
}
// MenuViewModel.cs
namespace Views
{
    public class MenuViewModel : ReactiveObject
    {
        public ObservableCollection<DialogItem> MenuItems { get; } = new ObservableCollection<DialogItem>();

        public MenuViewModel()
        {
            MenuItems.Add(new DialogItem("Edit", 224));
            MenuItems.Add(new DialogItem("View", 224));
        }
    }
}

DialogItem представляет элемент в меню

// DialogItem.cs
namespace Model
{
    public class DialogItem
    {
        public DialogItem(string description, int dialogId)
        {
            this.DialogId = dialogId;
            this.Description = description;
        }

        public int DialogId { get; }

        public string Description { get; }
    }
}

Затем, наконец, в MainWindow я включаю usercontrol следующим образом:

// MainWindow.xaml
<reactiveui:ReactiveWindow
        x:Class="Views.MainWindow"
....
>
    <Grid>
        <views:MenuView x:Name="MainMenu" />
    </Grid>
</reactiveui:ReactiveWindow>

Код позади

// MainWindow.xaml.cs
namespace Views
{
    public partial class MainWindow : ReactiveWindow<MainWindowModel>
    {
        public MainWindow()
        {
            InitializeComponent();
            this.WhenActivated(disposables =>
            {
        // BIND THE VIEWMODEL CREATED IN THE MAINWINDOW VIEWMODEL, IS THIS CORRECT?
                this.Bind(ViewModel,
                    vm => vm.MainMenuViewModel,
                    view => view.MainMenu.ViewModel
                ).DisposeWith(disposables);
            });
        }
    }
}
// MainWindowModel.cs
namespace Views
{
    public class MainWindowModel : ReactiveObject
    {
        public MenuViewModel MainMenuViewModel { get; }

        public MainWindowModel()
        {
            this.MainMenuViewModel = new MenuViewModel();
        }
    }
}

Элементы повторяются, но если я смотрю на дерево визуального представления, я вместо этого ViewModelViewHost элемент в ContentPresenterTextBlock

enter image description here

Здесь вы видите, что пункты меню отображаются неправильно. (они отображаются, но без текста из DataTemplate.

Обновление : использование Menu.ItemTemplate работает, но это не то, что я ищу.

<reactiveui:ReactiveUserControl
       x:Class="Views.MenuView"
...
>
    <Menu x:Name="RootMenu"
          IsMainMenu="True">
        <Menu.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Description}" />
            </DataTemplate>
        </Menu.ItemTemplate>
    </Menu>
</reactiveui:ReactiveUserControl>

1 Ответ

0 голосов
/ 31 октября 2019

Обсуждение этой проблемы в Slack с Гленном Уотсоном дало мне момент сброса. Поскольку я использовал код привязки RxUI, RxUI использует его логику локатора для поиска представления. RxUI будет искать представление, если не определено свойство ItemTemplate или DisplayPathMember. Эти представления регистрируются в контейнере Splat как представление для модели представления. Так что DataTemplates в <Menu.Resources> не рассматриваются. Это именно то, что показано на картинке. ViewModelViewHost создан, но, поскольку не найдено ни одного соответствующего представления, ничего не отображается.

Эту проблему можно решить, используя привязку XAML вместо кода, лежащего в основе привязки (для этого назначьте модель представления текстовому тексту данных!). Смотрите документы для получения дополнительной информации.

...