ViewModel 和 View 未绑定到列表框中的用户控件
ViewModel and View not getting bound for user control in listbox
我有一个 BooksListViewModel
和 BooksListView
,它只有一个名为 Books
的列表框,应该通过 ViewModel 中的 BindableCollection<BookViewModel> Books
属性 填充.
什么都没有显示,我想要么是 Book 列表框和 属性 没有正确绑定,要么是 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; }
}
图书列表视图:
<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;
}
}
}
图书视图:
<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));
}
}
}
我相信 'manually' 的 @Nkosi 更像是在代码隐藏中创建视图模型的新实例并设置为 DataContext 或从 XAML 端创建手动绑定。如果您通常知道如何使用依赖注入和 IoC 容器,我想您知道如何以正确的方式设置数据上下文,如果不知道,请告诉我,我会帮助您。无论如何,如果我在你那里,我会在 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 有您的集合,那么我就不会太担心了。这应该可以完成工作。
感谢@JackHughes,我得以修复它。 ViewModel 必须是 public,而不是内部的。将所有内容切换到 public 修复它。
我有一个 BooksListViewModel
和 BooksListView
,它只有一个名为 Books
的列表框,应该通过 ViewModel 中的 BindableCollection<BookViewModel> Books
属性 填充.
什么都没有显示,我想要么是 Book 列表框和 属性 没有正确绑定,要么是 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; }
}
图书列表视图:
<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;
}
}
}
图书视图:
<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));
}
}
}
我相信 'manually' 的 @Nkosi 更像是在代码隐藏中创建视图模型的新实例并设置为 DataContext 或从 XAML 端创建手动绑定。如果您通常知道如何使用依赖注入和 IoC 容器,我想您知道如何以正确的方式设置数据上下文,如果不知道,请告诉我,我会帮助您。无论如何,如果我在你那里,我会在 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 有您的集合,那么我就不会太担心了。这应该可以完成工作。
感谢@JackHughes,我得以修复它。 ViewModel 必须是 public,而不是内部的。将所有内容切换到 public 修复它。