【发布时间】:2022-12-22 00:06:55
【问题描述】:
我正在尝试使用 Avalonia 和 ReactiveUI 来显示从本地数据库中提取的图像列表框。我的实现基于 ReactiveUI 在其文档中的示例:here。我通过为主页创建一个视图和视图模型来实现它,其中包含为各个图像制作的视图模型列表。从我从演示中得到的信息,Avalonia 应该识别图像视图模型并在列表框中显示相应的用户控件,但列表框什么都不显示,元素检查器报告列表框已连接到列表的通用对象。我不确定我做错了什么,但我怀疑这与它没有在图像视图模型和图像视图之间建立联系有关。
BrowserViewModel.cs (MainWindowViewModel):
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using Avalonia.NETCoreMVVMApp.Models;
using ReactiveUI;
namespace Avalonia.NETCoreMVVMApp.ViewModels
{
public class BrowserViewModel : ReactiveObject
{
//how many results to display per page. Right now in the absence of pages it's used as the limit for how many results
//I pull from the database
private const int PageResultSize = 50;
//Observable property for the list of results pulled from the databse
private readonly ObservableAsPropertyHelper<List<BrowserResultViewModel>> _browserResults;
public List<BrowserResultViewModel> BrowserResults => _browserResults.Value;
//reactive command used to link the SubmitButton click event to the service that retrieves images from the database
public ReactiveCommand<Unit, List<BrowserResultViewModel>> FetchImages { get; }
//property for the search query out in through a text box
private string _searchQuery;
public string SearchQuery
{
get => _searchQuery;
set => this.RaiseAndSetIfChanged(ref _searchQuery, value);
}
//property for keeping track of the page the browser is on. (Not yet implemented)
private int _pageNumber;
public int PageNumber
{
get => _pageNumber;
set => this.RaiseAndSetIfChanged(ref _pageNumber, value);
}
public BrowserViewModel()
{
FetchImages = ReactiveCommand.CreateFromTask(FetchImagesAsync);
_browserResults = FetchImages.ToProperty(
this, x => x.BrowserResults, scheduler: RxApp.MainThreadScheduler);
}
//background function for the FetchImage command
public async Task<List<BrowserResultViewModel>> FetchImagesAsync()
{
var context = new ApplicationContext();
var results = context.Images
.Take(PageResultSize)
.Select(x => new BrowserResultViewModel(x.FileUri, x.Tags
.Select(x => x.Name)
.ToList()))
.ToList();
return results;
}
}
}
浏览器结果视图模型.cs:
using System;
using System.Collections.Generic;
using ReactiveUI;
namespace Avalonia.NETCoreMVVMApp.ViewModels
{
public class BrowserResultViewModel : ReactiveObject
{
//Uri containing corresponding image file path.
public Uri ImageUri;
//property for an image's corresponding tags (Not yet implemented)
private List<string> _tags;
public List<string> Tags
{
get => _tags;
set => this.RaiseAndSetIfChanged(ref _tags, value);
}
public BrowserResultViewModel(Uri imageUri, List<string> tags)
{
ImageUri = imageUri;
Tags = tags;
}
}
}
BrowserView.cs(主窗口视图):
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Mixins;
using Avalonia.Markup.Xaml;
using Avalonia.NETCoreMVVMApp.ViewModels;
using Avalonia.ReactiveUI;
using ReactiveUI;
namespace Avalonia.NETCoreMVVMApp.Views
{
public partial class BrowserResultView : ReactiveUserControl<BrowserResultViewModel>
{
public BrowserResultView()
{
this.WhenActivated(disposable =>
{
//this binds the uri for an image to the image control in avalonia.
this.OneWayBind(ViewModel,
viewModel => viewModel.ImageUri,
view => view.Thumbnail.Source)
.DisposeWith(disposable);
});
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}
浏览器结果视图.cs:
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Mixins;
using Avalonia.Markup.Xaml;
using Avalonia.NETCoreMVVMApp.ViewModels;
using Avalonia.ReactiveUI;
using ReactiveUI;
namespace Avalonia.NETCoreMVVMApp.Views
{
public partial class BrowserResultView : ReactiveUserControl<BrowserResultViewModel>
{
public BrowserResultView()
{
this.WhenActivated(disposable =>
{
//this binds the uri for an image to the image control in avalonia.
this.OneWayBind(ViewModel,
viewModel => viewModel.ImageUri,
view => view.Thumbnail.Source)
.DisposeWith(disposable);
});
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}
浏览器结果视图.axml:
<UserControl xmlns="https://github.com/avaloniaui"
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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Avalonia.NETCoreMVVMApp.Views.BrowserResultView">
<Grid>
<Image x:Name="Thumbnail" Margin="6" Width="64" Height="64" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</UserControl>
主窗口.xaml:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Avalonia.NETCoreMVVMApp.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactiveUi="http://reactiveui.net"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Avalonia.NETCoreMVVMApp.Views.MainWindow"
Icon="/Assets/avalonia-logo.ico"
Title="Avalonia.NETCoreMVVMApp">
<Grid RowDefinitions="1*, 20*" ColumnDefinitions="*">
<Grid RowDefinitions="*" ColumnDefinitions="*, 70">
<TextBox x:Name="searchBox"/>
<Button Grid.Column="1" x:Name="submitSearchBtn">Submit</Button>
</Grid>
<ListBox x:Name="browserResultsListBox" Grid.Row="1"/>
</Grid>
</Window>
【问题讨论】:
-
我的回答有帮助吗?
标签: c# reactiveui avaloniaui