ViewModel и View не привязываются к пользовательскому элементу управления в списке - PullRequest
0 голосов
/ 04 октября 2018

У меня есть BooksListViewModel & BooksListView, в котором есть только список со списком с именем Books, который должен быть заполнен с помощью свойства BindableCollection<BookViewModel> Books в ViewModel.

Ничего не появляется, и яЯ думаю, что либо список и свойство книги не связаны должным образом, либо это BookView и BookViewModel, но я не могу понять, какие именно.

Я также использую SimpleInjector, и я думаю,может я неправильно настроил?Я скопировал большую часть кода из примеров возможностей Caliburn - в частности, из примера Bindings.

Код для загрузчика:

namespace WPFCaliburnUI
{
    public class Bootstrapper : BootstrapperBase
    {
        private Container _container;

        public Bootstrapper()
        {
            Initialize();
        }

        protected override void Configure()
        {
// Mostly taken from here: https://www.c-sharpcorner.com/blogs/migrating-to-simple-injector-30-with-caliburn-micro-bootstrap-changes
            this._container = new Container();
            this._container.Options.DefaultScopedLifestyle = new ThreadScopedLifestyle();

            this._container.RegisterSingleton<IWindowManager, WindowManager>();
            this._container.RegisterSingleton<IEventAggregator, EventAggregator>();

            this._container.Register<ShellWindowViewModel>();
            this._container.Register<BooksListViewModel>();

            SetupContextAndCrudServices() // Removed this method since it's a little long, 
                                          // but I did verify it is working correctly. 
                                          // Just adds the context and other stuff to the container.

            this._container.Verify();
        }

        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewFor<ShellWindowViewModel>();
        }

        protected override IEnumerable<Assembly> SelectAssemblies()
        {
            return new[] { Assembly.GetExecutingAssembly() };
        }

        protected override object GetInstance(Type service, string key)
        {
            return this._container.GetInstance(service);
        }

        protected override IEnumerable<object> GetAllInstances(Type service)
        {
            IServiceProvider provider = this._container;
            Type collectionType = typeof(IEnumerable<>).MakeGenericType(service);
            var services = (IEnumerable<object>)provider.GetService(collectionType);
            return services ?? Enumerable.Empty<object>();
        }

        protected override void BuildUp(object instance)
        {
            var registration = this._container.GetRegistration(instance.GetType(), true);
            registration.Registration.InitializeInstance(instance);
        }
    }
}

BooksListViewModel:

internal class BooksListViewModel : Screen
{
    private readonly ICrudServices _service;

    private BookViewModel _selectedBook;

    public BookViewModel SelectedBook {
        get => this._selectedBook;
        set => Set(ref this._selectedBook, value);
    }

    public BooksListViewModel(ICrudServices service)
    {
        this._service = service;
        var booksQuery = _service.ReadManyNoTracked<BookListDto>().Take(10);
        var bcBooks = new Collection<BookViewModel>();
        foreach (var bookDto in booksQuery)
        {
            bcBooks.Add(new BookViewModel(bookDto.Title, bookDto.AuthorsOrdered));
        }
        // I did double check that this worked, Books has 10 items.
        this.Books = new BindableCollection<BookViewModel>(bcBooks);
    }

    public BindableCollection<BookViewModel> Books { get; private set; }
}

BooksListView:

<Page
    x:Class="WPFCaliburnUI.Views.BooksListView"
    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:local="clr-namespace:WPFCaliburnUI.ViewModels"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="BooksListView"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">

    <Grid Name="ContentPanel">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <ListBox x:Name="Books">
        </ListBox>

        <StackPanel
            Grid.Row="1"
            Margin="0,12"
            Orientation="Horizontal">
            <TextBlock Margin="0,0,6,0" Text="Selected:" />
            <TextBlock x:Name="SelectedBook_Title" />
        </StackPanel>
    </Grid>
</Page>

BookViewModel:

namespace WPFCaliburnUI.ViewModels
{
    internal class BookViewModel
    {
        public string Title { get; set; }
        public string Author { get; set; }

        public BookViewModel(string title, string author)
        {
            this.Title = title;
            this.Author = author;
        }
    }
}

BookView:

<UserControl
    x:Class="WPFCaliburnUI.Views.BookView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:cal="http://www.caliburnproject.org"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:WPFCaliburnUI.Views"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    d:DesignHeight="450"
    d:DesignWidth="600"
    mc:Ignorable="d">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Ellipse
            Grid.Column="0"
            Width="48"
            Height="48"
            Margin="0,0,12,0"
            VerticalAlignment="Top"
            Fill="DarkBlue" />

        <StackPanel Grid.Column="1">
            <TextBlock x:Name="Title"
                FontSize="16"
                FontWeight="SemiBold" />
            <TextBlock x:Name="Author" />
        </StackPanel>
    </Grid>
</UserControl>

Редактировать: Некоторые люди спрашивают, как называется BooksListViewModel, поэтому воткод от ShellWindowViewModel

namespace WPFCaliburnUI.ViewModels
{
    internal class ShellWindowViewModel : Screen
    {
        private readonly Container _container;
        private readonly IWindowManager _windowManager;
        private INavigationService navigationService;

        public ShellWindowViewModel(Container container, IWindowManager windowManager)
        {
            this._container = container;
            this._windowManager = windowManager;
        }

        public void RegisterFrame(Frame frame)
        {
            navigationService = new FrameAdapter(frame);

            navigationService.NavigateToViewModel(typeof(BooksListViewModel));
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Благодаря @JackHughes я смог это исправить.ViewModels должна быть публичной, а не внутренней.Переключение всего на публичное исправило это.

0 голосов
/ 05 октября 2018

Я полагаю, что @Nkosi «вручную» означало больше похоже на создание нового экземпляра вашей модели представления в коде и настройку в качестве DataContext или создание привязок вручную со стороны XAML.Если вы знаете, как работать с внедрением зависимостей и IoC-контейнерами в целом, я полагаю, что вы знаете, как правильно настроить datacontext, если нет, то просто дайте мне знать, и я помогу вам.В любом случае, если бы я был на вашем месте, я бы установил привязки в xaml, например:

 <Grid Name="ContentPanel">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <ListBox x:Name="Books"
             ItemsSource="{Binding Books}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Title}" />
                    <TextBlock Text="{Binding Author}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

        <StackPanel
        Grid.Row="1"
        Margin="0,12"
        Orientation="Horizontal">
        <TextBlock Margin="0,0,6,0" Text="Selected:" />
        <TextBlock x:Name="SelectedBook_Title" />
    </StackPanel>
</Grid>

Если бы в DataContext вашего View была ваша коллекция, я бы не стал сильно беспокоиться.Это должно сделать работу.

...