feat(commerce): Use uno.reactive in commerce demo app

This commit is contained in:
David 2021-11-12 17:11:42 -05:00
Родитель 9c206b26c1
Коммит cea931728c
21 изменённых файлов: 802 добавлений и 248 удалений

Просмотреть файл

@ -232,3 +232,9 @@ dotnet_diagnostic.IDE0022.severity = none
# CS1998: This async method lacks 'await' operators and will run synchronously.
dotnet_diagnostic.CS1998.severity = none
# SA1101: Prefix local calls with this
dotnet_diagnostic.SA1101.severity = none
# SA1309: Field names should not begin with underscore
dotnet_diagnostic.SA1309.severity = none

Просмотреть файл

@ -71,6 +71,7 @@
<PackageReference Include="Uno.UniversalImageLoader" Version="1.9.33" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="System.Linq.Async" Version="4.0.0" />
<PackageReference Include="Xamarin.AndroidX.AppCompat.AppCompatResources">
<Version>1.2.0.5</Version>
</PackageReference>
@ -143,6 +144,14 @@
<Project>{5123670c-9756-4c9e-9844-f4a9c0aee633}</Project>
<Name>Uno.Extensions.Serialization</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Uno.Extensions.Reactive\Uno.Extensions.Reactive.csproj">
<Project>{74D93A0B-42F9-45A6-8AC3-684DAE9659A8}</Project>
<Name>Uno.Extensions.Reactive</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Uno.Extensions.Reactive.View\Uno.Extensions.Reactive.View.csproj">
<Project>{7516C1F2-6CCB-4B59-91B7-E6D4B4EA5835}</Project>
<Name>Uno.Extensions.Reactive.View</Name>
</ProjectReference>
</ItemGroup>
<Import Project="..\Commerce.Shared\Commerce.Shared.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
@ -154,4 +163,4 @@
<Compile Remove="$(_AndroidResourceDesignerFile)" />
</ItemGroup>
</Target>
</Project>
</Project>

Просмотреть файл

@ -17,6 +17,8 @@
<ToolkitResources xmlns="using:Uno.UI.ToolkitLib" />
<!--<MaterialToolkitResources xmlns="using:Uno.Toolkit.Material" />-->
<ResourceDictionary Source="ms-appx:///Styles/FeedView.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Просмотреть файл

@ -74,9 +74,9 @@ namespace Commerce
.AddSingleton<INavigationBindingHandler, NavigationViewItemNavigationBindingHandler>()
.AddTransient<LoginViewModel>()
.AddTransient<ProductsViewModel>()
.AddTransient<ProductsViewModel.BindableProductsViewModel>()
.AddTransient<FilterViewModel>()
.AddTransient<ProductDetailsViewModel>()
.AddTransient<ProductDetailsViewModel.BindableProductDetailsViewModel>()
.AddViewModelData<Product>()
.AddTransient<DealsViewModel>()
.AddSingleton<IProductService>(sp => new ProductService("products.json"));
@ -86,11 +86,13 @@ namespace Commerce
.EnableUnoLogging();
var mapping = Host.Services.GetService<IRouteMappings>();
mapping.Register(new RouteMap("Login", typeof(LoginPage), typeof(LoginViewModel.BindableLoginViewModel)));
mapping.Register(new RouteMap(typeof(CommerceHomePage).Name, typeof(CommerceHomePage),
RegionInitialization: (region, nav) => nav.Route.Next().IsEmpty() ?
nav with { Route = nav.Route.Append(Route.NestedRoute("Products")) } :
nav));
mapping.Register(new RouteMap("Products", typeof(FrameView),
ViewModel: typeof(ProductsViewModel.BindableProductsViewModel),
RegionInitialization: (region, nav) => nav.Route.Next().IsEmpty() ?
nav with { Route = nav.Route.AppendPage<ProductsPage>() } : nav with
{
@ -104,7 +106,8 @@ namespace Commerce
nav with { Route = nav.Route with { Path = "+DealsPage/HotDeals" } }));
mapping.Register(new RouteMap("ProductDetails",
typeof(ProductDetailsPage),
typeof(ProductDetailsViewModel), typeof(Product),
typeof(ProductDetailsViewModel.BindableProductDetailsViewModel),
typeof(Product),
BuildQueryParameters: entity => new Dictionary<string, string> { { "ProductId", (entity as Product)?.ProductId + "" } }));
mapping.Register(new RouteMap(typeof(CartDialog).Name, typeof(CartDialog),
RegionInitialization: (region, nav) => nav.Route.Next().IsEmpty() ?
@ -183,7 +186,7 @@ namespace Commerce
});
var nav = Host.Services.GetService<INavigator>();
var navResult = nav.NavigateToViewAsync<LoginPage>(this);
var navResult = nav.NavigateToRouteAsync(this, "Login");
//var navResult = nav.NavigateToRouteAsync(this, "/CommerceHomePage/Products/ProductDetails?ProductId=3");
}

Просмотреть файл

@ -30,8 +30,11 @@
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\DealsViewModel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\FilterViewModel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\LoginViewModel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\LoginViewModel.g.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ProductDetailsViewModel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ProductDetailsViewModel.g.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ProductsViewModel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ProductsViewModel.g.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Views\CartDialog.xaml.cs">
<DependentUpon>CartDialog.xaml</DependentUpon>
</Compile>
@ -71,6 +74,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Styles\FeedView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Views\CartDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

Просмотреть файл

@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Windows.Storage;
@ -50,67 +52,23 @@ public class ProductService : JsonDataService<Product>, IProductService
}
public Task<Product[]> GetProducts()
public async Task<IEnumerable<Product>> GetProducts(string? term, CancellationToken ct)
{
return base.GetEntities();
//return new List<Product>
//{
// new Product{ProductId=1, Name="ProMaster headphones", Category="Technology", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto1.png"},
// new Product{ProductId=2, Name="Ray-gen sunglasses", Category="Accessories", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto2.png"},
// new Product{
// ProductId=3,
// Name="Jeffords sneakers",
// Category="Men's shoes",
// FullPrice="$130",
// Price="$99",
// Discount="Save 25%",
// Photo="ms-appx:///Assets/Photos/stockphoto3.png",
// Description="The classic low top silhouette is reinvented with a water-resistant feature. The perfect go-to pair to sport on light rainy days!",
// Reviews= new[]{
// new Review { Name = "Jean-Ralphio", Message = "Really good shoes. Love them" },
// new Review{Name="Eric", Message="Instant buy, instant classic"},
// new Review{Name="Lisa Kudrow", Message="I feel like walking on clouds with these shoes. Never experienced somthing simliar"}
// }
// },
// new Product{ProductId=4, Name="Wheel watch 2019", Category="Watches", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto4.png"},
// new Product{ProductId=1, Name="ProMaster headphones", Category="Technology",FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto1.png"},
// new Product{ProductId=2, Name="Ray-gen sunglasses", Category="Accessories", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto2.png"},
// new Product{ProductId=3, Name="Jeffords sneakers", Category="Men's shoes",FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto3.png"},
// new Product{ProductId=4, Name="Wheel watch 2019", Category="Watches", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto4.png"},
// new Product{ProductId=1, Name="ProMaster headphones", Category="Technology",FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto1.png"},
// new Product{ProductId=2, Name="Ray-gen sunglasses", Category="Accessories", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto2.png"},
// new Product{ProductId=3, Name="Jeffords sneakers", Category="Men's shoes",FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto3.png"},
// new Product{ProductId=4, Name="Wheel watch 2019", Category="Watches", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto4.png"},
// new Product{ProductId=1, Name="ProMaster headphones", Category="Technology",FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto1.png"},
// new Product{ProductId=2, Name="Ray-gen sunglasses", Category="Accessories", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto2.png"},
// new Product{ProductId=3, Name="Jeffords sneakers", Category="Men's shoes",FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto3.png"},
// new Product{ProductId=4, Name="Wheel watch 2019", Category="Watches", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto4.png"},
// new Product{ProductId=1, Name="ProMaster headphones", Category="Technology",FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto1.png"},
// new Product{ProductId=2, Name="Ray-gen sunglasses", Category="Accessories", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto2.png"},
// new Product{
// ProductId=3,
// Name="Jeffords sneakers",
// Category="Men's shoes",
// FullPrice="$130",
// Price="$99",
// Discount="Save 25%",
// Photo="ms-appx:///Assets/Photos/stockphoto3.png",
// Description="The classic low top silhouette is reinvented with a water-resistant feature. The perfect go-to pair to sport on light rainy days!",
// Reviews= new[]{
// new Review { Name = "Jean-Ralphio", Message = "Really good shoes. Love them" },
// new Review{Name="Eric", Message="Instant buy, instant classic"},
// new Review{Name="Lisa Kudrow", Message="I feel like walking on clouds with these shoes. Never experienced somthing simliar"}
// }
// },
// new Product{ProductId=4, Name="Wheel watch 2019", Category="Watches", FullPrice="$130",Price="$99", Discount="Save 25%", Photo="ms-appx:///Assets/Photos/stockphoto4.png"},
await Task.Delay(new Random(DateTime.Now.Millisecond).Next(100, 1000), ct);
//};
var products = (await GetEntities()).AsEnumerable();
if (term is not null)
{
products = products.Where(p => p.Name.Contains(term));
}
return products;
}
}
public interface IProductService
{
Task<Product[]> GetProducts();
Task<IEnumerable<Product>> GetProducts(string? term, CancellationToken ct);
}
public class Product

Просмотреть файл

@ -0,0 +1,294 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:reactive="using:Uno.Extensions.Reactive">
<Style TargetType="reactive:FeedView">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="reactive:FeedView">
<Grid>
<VisualStateManager.CustomVisualStateManager>
<reactive:SmoothVisualStateManager>
<reactive:SmoothVisualStateRule MinDuration="0:0:0.500" />
<reactive:SmoothVisualStateRule Group="ProgressGroup" To="Indeterminate" Delay="0:0:0.250" />
</reactive:SmoothVisualStateManager>
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DataGroup">
<VisualState x:Name="Undefined" />
<VisualState x:Name="None">
<VisualState.Setters>
<Setter Target="UndefinedPresenter.Visibility" Value="Collapsed" />
<Setter Target="NonePresenter.Visibility" Value="Visible" />
<Setter Target="SomePresenter.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Some">
<VisualState.Setters>
<Setter Target="UndefinedPresenter.Visibility" Value="Collapsed" />
<Setter Target="NonePresenter.Visibility" Value="Collapsed" />
<Setter Target="SomePresenter.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ErrorGroup">
<VisualStateGroup.Transitions>
<VisualTransition To="Error">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ErrorPresenter"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame
KeyTime="0:0:0"
Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Storyboard.TargetName="ErrorPresenterTransform"
Storyboard.TargetProperty="Y"
From="-50"
To="0"
Duration="0:0:.5"/>
</Storyboard>
</VisualTransition>
<VisualTransition From="Error">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ErrorPresenter"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame
KeyTime="0:0:0"
Value="Visible"/>
<DiscreteObjectKeyFrame
KeyTime="0:0:0.5"
Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Storyboard.TargetName="ErrorPresenterTransform"
Storyboard.TargetProperty="Y"
To="-50"
Duration="0:0:.5"/>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="NoError" />
<VisualState x:Name="Error">
<VisualState.Setters>
<Setter Target="ErrorPresenter.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ProgressGroup">
<VisualState x:Name="Final" />
<VisualState x:Name="Indeterminate">
<VisualState.Setters>
<Setter Target="LoadingPresenter.Visibility" Value="Visible" />
</VisualState.Setters>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="LoadingPresenter"
Storyboard.TargetProperty="Opacity"
From=".5"
To=".8"
Duration="0:0:0.250"
AutoReverse="True"
RepeatBehavior="Forever"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter
x:Name="UndefinedPresenter"
Content="{TemplateBinding Undefined}"
ContentTemplate="{TemplateBinding UndefinedTemplate}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Visibility="Visible" />
<ContentPresenter
x:Name="NonePresenter"
Content="{TemplateBinding None}"
ContentTemplate="{TemplateBinding NoneTemplate}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Visibility="Collapsed" />
<ContentPresenter
x:Name="SomePresenter"
Content="{TemplateBinding State}"
ContentTemplate="{TemplateBinding ValueTemplate}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Visibility="Collapsed" />
<Border
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Background="Red"
x:Name="ErrorPresenter"
Visibility="Collapsed"
Height="50">
<Border.RenderTransform>
<TranslateTransform x:Name="ErrorPresenterTransform" />
</Border.RenderTransform>
<ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=State.Error}" />
</Border>
<Border
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Orange"
x:Name="LoadingPresenter"
Visibility="Collapsed"
Opacity="0">
<TextBlock Text="Loading" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="reactive:FeedView" x:Key="SingleStateFeedView">
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="reactive:FeedView">
<Grid
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
<VisualStateManager.CustomVisualStateManager>
<reactive:SmoothVisualStateManager>
<reactive:SmoothVisualStateRule MinDuration="0:0:0.500" />
<reactive:SmoothVisualStateRule Group="ProgressGroup" To="Indeterminate" Delay="0:0:0.250" />
</reactive:SmoothVisualStateManager>
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DataGroup">
<VisualState x:Name="Undefined" />
<VisualState x:Name="None">
<VisualState.Setters>
<Setter Target="UndefinedPresenter.Visibility" Value="Collapsed" />
<Setter Target="NonePresenter.Visibility" Value="Visible" />
<Setter Target="SomePresenter.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Some">
<VisualState.Setters>
<Setter Target="UndefinedPresenter.Visibility" Value="Collapsed" />
<Setter Target="NonePresenter.Visibility" Value="Collapsed" />
<Setter Target="SomePresenter.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ErrorGroup">
<VisualState x:Name="NoError" />
<VisualState x:Name="Error">
<VisualState.Setters>
<Setter Target="ErrorPresenter.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ProgressGroup">
<VisualStateGroup.Transitions>
<VisualTransition To="Indeterminate">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="LoadingWheel"
Storyboard.TargetProperty="IsActive">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="True" />
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Storyboard.TargetName="LoadingPresenter"
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
Duration="0:0:0.100" />
</Storyboard>
</VisualTransition>
<VisualTransition From="Indeterminate">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="LoadingPresenter"
Storyboard.TargetProperty="Opacity"
From="1"
To="0"
Duration="0:0:0.100" />
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Final" />
<VisualState x:Name="Indeterminate">
<VisualState.Setters>
<Setter Target="LoadingPresenter.Visibility" Value="Visible" />
<Setter Target="LoadingPresenter.Opacity" Value="1" />
<Setter Target="LoadingWheel.IsActive" Value="True" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter
x:Name="UndefinedPresenter"
Content="{TemplateBinding Undefined}"
ContentTemplate="{TemplateBinding UndefinedTemplate}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Visibility="Visible" />
<ContentPresenter
x:Name="NonePresenter"
Content="{TemplateBinding None}"
ContentTemplate="{TemplateBinding NoneTemplate}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Visibility="Collapsed" />
<ContentPresenter
x:Name="SomePresenter"
Content="{TemplateBinding State}"
ContentTemplate="{TemplateBinding ValueTemplate}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Visibility="Collapsed" />
<ContentPresenter
x:Name="ErrorPresenter"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Visibility="Collapsed"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=State.Error}" />
<Border
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
x:Name="LoadingPresenter"
Visibility="Collapsed"
Opacity="0">
<ProgressRing
x:Name="LoadingWheel"
IsActive="False"
Width="50"
Height="50" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

Просмотреть файл

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Commerce.Services;
using Uno.Extensions;
@ -21,7 +22,7 @@ public class DealsViewModel
private async Task Load(IProductService products)
{
var productItems = await products.GetProducts();
var productItems = await products.GetProducts(null, CancellationToken.None);
productItems.ForEach(p =>
{
HotDeals.Add(p);

Просмотреть файл

@ -1,15 +1,48 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Commerce.Services;
using Uno.Extensions.Navigation;
using Uno.Extensions.Reactive;
using Windows.ApplicationModel.Core;
namespace Commerce.ViewModels
namespace Commerce.ViewModels;
public partial class LoginViewModel
{
public class LoginViewModel
private readonly INavigator _navigator;
private readonly IState<string> _error;
private LoginViewModel(
INavigator navigator,
IFeed<string> userName,
IFeed<string> password,
IState<string> error,
ICommandBuilder login)
{
public LoginViewModel()
_navigator = navigator;
_error = error;
login
.Given(Feed.Combine(userName, password))
.When(CanLogin)
.Then(Login);
}
private bool CanLogin((string userName, string password) values)
=> values is { userName.Length: > 0 } and { password.Length: > 0 };
private async ValueTask Login((string userName, string password) values, CancellationToken ct)
{
if (values is { userName.Length: >= 3 } and { password.Length: >= 3 })
{
await _error.Set(default, ct);
await Task.Delay(1000, ct);
CoreApplication.MainView?.DispatcherQueue.TryEnqueue(() => _navigator.NavigateToRouteAsync(this, "/-/CommerceHomePage", cancellation: ct));
}
else
{
await _error.Set("Login and password must be at least 3 characters long.", ct);
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Uno.Extensions.Navigation;
using Uno.Extensions.Reactive;
namespace Commerce.ViewModels;
public partial class LoginViewModel : IAsyncDisposable
{
public class BindableLoginViewModel : BindableViewModelBase
{
private readonly Bindable<string> _userName;
private readonly Bindable<string> _password;
private readonly Bindable<string> _error;
public BindableLoginViewModel(
INavigator navigator,
string? defaultUserName = default,
string? defaultPassword = default,
string? defaultError = default)
{
_userName = new Bindable<string>(Property<string>(nameof(UserName), defaultUserName, out var userNameSubject));
_password = new Bindable<string>(Property<string>(nameof(Password), defaultPassword, out var passwordSubject));
_error = new Bindable<string>(Property<string>(nameof(Error), defaultError, out var errorSubject));
var login = new CommandBuilder<object?>(nameof(Login));
var vm = new LoginViewModel(navigator, userNameSubject, passwordSubject, errorSubject, login);
var ctx = SourceContext.GetOrCreate(vm);
SourceContext.Set(this, ctx);
RegisterDisposable(vm);
Model = vm;
Login = login.Build(ctx);
}
public LoginViewModel Model { get; }
public string UserName
{
get => _userName.GetValue();
set => _userName.SetValue(value);
}
public string Password
{
get => _password.GetValue();
set => _password.SetValue(value);
}
public string Error
{
get => _error.GetValue();
set => _error.SetValue(value);
}
public IAsyncCommand Login { get; }
}
/// <inheritdoc />
public ValueTask DisposeAsync()
=> SourceContext.Find(this)?.DisposeAsync() ?? default;
}

Просмотреть файл

@ -2,36 +2,47 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Commerce.Services;
using System.Threading.Tasks;
using Uno.Extensions.Reactive;
namespace Commerce.ViewModels;
public class ProductDetailsViewModel : ObservableObject
public partial class ProductDetailsViewModel
{
private Product _product;
private readonly IProductService _products;
private readonly Product _product;
private readonly IDictionary<string, object> _parameters;
public Product Product { get => _product; set => SetProperty(ref _product, value); }
public ProductDetailsViewModel(IProductService products, Product p, IDictionary<string, object> parameters)
{
Load(products, p, parameters);
}
private async Task Load(IProductService products, Product p, IDictionary<string, object> parameters)
public ProductDetailsViewModel(
IProductService products,
Product product,
IDictionary<string, object> parameters)
{
_products = products;
_product = product;
_parameters = parameters;
}
if (p is not null)
public IFeed<Product> Product => Feed.Async(Load);
private async ValueTask<Option<Product>> Load(CancellationToken ct)
{
await Task.Delay(5000);
if (_product is not null)
{
Product = p;
return _product;
}
else if(_parameters.TryGetValue("ProductId", out var id))
{
return (await _products.GetProducts(null, CancellationToken.None)).FirstOrDefault(x => x.ProductId + "" == id.ToString());
}
else
{
if (parameters.TryGetValue("ProductId", out var id))
{
Product = (await products.GetProducts()).FirstOrDefault(x => x.ProductId + "" == id.ToString());
}
return default;
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Commerce.Services;
using Uno.Extensions.Reactive;
namespace Commerce.ViewModels;
partial class ProductDetailsViewModel : IAsyncDisposable
{
public class BindableProductDetailsViewModel : BindableViewModelBase
{
public BindableProductDetailsViewModel(
IProductService service,
Product product,
IDictionary<string, object> parameters)
{
var vm = new ProductDetailsViewModel(service, product, parameters);
var ctx = SourceContext.GetOrCreate(vm);
SourceContext.Set(this, ctx);
RegisterDisposable(vm);
Model = vm;
Product = ctx.GetOrCreateState(vm.Product);
}
public ProductDetailsViewModel Model { get; }
public IFeed<Product> Product { get; }
}
/// <inheritdoc />
public ValueTask DisposeAsync()
=> SourceContext.Find(this)?.DisposeAsync() ?? default;
}

Просмотреть файл

@ -1,35 +1,43 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using CommunityToolkit.Mvvm.ComponentModel;
using Commerce.Services;
using Uno.Extensions;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Commerce.Services;
using Uno.Extensions.Reactive;
namespace Commerce.ViewModels;
public class ProductsViewModel : ObservableObject
public partial class ProductsViewModel
{
private string _filterQuery;
private readonly IProductService _products;
private readonly IFeed<string> _searchTerm;
private readonly IState<string> _filterQuery;
public string FilterQuery { get => _filterQuery; set => SetProperty(ref _filterQuery,value); }
public ObservableCollection<Product> Products { get; } = new ObservableCollection<Product>();
public ProductsViewModel(IProductService products)
{
Load(products);
}
private async Task Load(IProductService products)
private ProductsViewModel(
IProductService products,
[DefaultValue("")] IFeed<string> searchTerm,
[DefaultValue("")] IState<string> filterQuery)
{
var productItems = await products.GetProducts();
productItems.ForEach(p => Products.Add(p));
FilterQuery = "Query-" + DateTime.Now.ToString("HH:mm:ss:ffff");
_products = products;
_searchTerm = searchTerm;
_filterQuery = filterQuery;
}
public IFeed<Product[]> Items => Feed
.Combine(_searchTerm.SelectAsync(Load), _filterQuery)
.Select(FilterProducts);
private async ValueTask<Product[]> Load(string searchTerm, CancellationToken ct)
{
var products = await _products.GetProducts(searchTerm, ct);
return products.ToArray();
}
private Product[] FilterProducts((Product[] products, string filterQuery) inputs)
{
// TODO: Apply filter here
return inputs.products;
}
}

Просмотреть файл

@ -0,0 +1,53 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Commerce.Services;
using Uno.Extensions.Reactive;
namespace Commerce.ViewModels;
public partial class ProductsViewModel : IAsyncDisposable
{
public class BindableProductsViewModel : BindableViewModelBase
{
private readonly Bindable<string> _searchTerm;
private readonly Bindable<string> _filterQuery;
public BindableProductsViewModel(
IProductService products,
string? defaultSearchTerm = "",
string? defaultFilterQuery = "")
{
_searchTerm = new Bindable<string>(Property(nameof(SearchTerm), defaultSearchTerm, out var searchTermSubject));
_filterQuery = new Bindable<string>(Property(nameof(FilterQuery), defaultFilterQuery, out var filterQuerySubject));
var vm = new ProductsViewModel(products, searchTermSubject, filterQuerySubject);
var ctx = SourceContext.GetOrCreate(vm);
SourceContext.Set(this, ctx);
RegisterDisposable(vm);
Model = vm;
Items = ctx.GetOrCreateState(vm.Items);
}
public ProductsViewModel Model { get; }
public IFeed<Product[]> Items { get; }
public string SearchTerm
{
get => _searchTerm.GetValue();
set => _searchTerm.SetValue(value);
}
public string FilterQuery
{
get => _filterQuery.GetValue();
set => _filterQuery.SetValue(value);
}
}
/// <inheritdoc />
public ValueTask DisposeAsync()
=> SourceContext.Find(this)?.DisposeAsync() ?? default;
}

Просмотреть файл

@ -39,25 +39,28 @@
<TextBox PlaceholderText="Email"
Margin="0,8"
MinWidth="200"
Name="UsernameText" />
Name="UsernameText"
Text="{x:Bind VM.UserName, Mode=TwoWay}"/>
<PasswordBox Margin="0,8"
PlaceholderText="Password"
MinWidth="200" />
MinWidth="200"
Password="{x:Bind VM.Password, Mode=TwoWay}" />
<HyperlinkButton Content="Forgot password?" />
<Button Content="LOGIN"
<TextBlock Text="{Binding Error}" Foreground="DarkRed" HorizontalAlignment="Center" />
<Button Content="LOGIN"
HorizontalAlignment="Stretch"
Margin="0,8"
nav:Navigation.Request="/-/CommerceHomePage" />
<TextBlock Text="Legal mentions" HorizontalAlignment="Center" />
</StackPanel>
Command="{Binding Login}" />
<TextBlock Text="Legal mentions" HorizontalAlignment="Center" />
</StackPanel>
<Grid x:Name="ProgressOverlay"
Visibility="Collapsed">
Visibility="{Binding Login.IsExecuting}">
<Border Background="White"
Opacity="0.7"/>
<ProgressRing x:Name="Progress"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsActive="False" />
IsActive="{Binding Login.IsExecuting}" />
</Grid>
</Grid>

Просмотреть файл

@ -16,6 +16,7 @@ using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Commerce.ViewModels;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
@ -29,13 +30,16 @@ namespace Commerce
public LoginPage()
{
this.InitializeComponent();
}
}
private INavigator navigator;
public void Inject(INavigator entity)
{
navigator = entity;
}
DataContext = VM = new LoginViewModel.BindableLoginViewModel(navigator);
}
public LoginViewModel.BindableLoginViewModel VM { get; private set; }
public async Task<bool> Stop(NavigationRequest request)
{

Просмотреть файл

@ -1,75 +1,79 @@
<Page x:Class="Commerce.ProductDetailsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Commerce"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:fake="using:Commerce.DesignTime"
xmlns:controls="using:Microsoft.UI.Xaml.Controls"
xmlns:nav="using:Uno.Extensions.Navigation.Controls"
xmlns:toolkit="using:Uno.UI.ToolkitLib"
mc:Ignorable="d fake"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Commerce"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:fake="using:Commerce.DesignTime"
xmlns:controls="using:Microsoft.UI.Xaml.Controls"
xmlns:nav="using:Uno.Extensions.Navigation.Controls"
xmlns:toolkit="using:Uno.UI.ToolkitLib"
xmlns:reactive="using:Uno.Extensions.Reactive"
mc:Ignorable="d fake"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid d:DataContext="{d:DesignInstance fake:FakeProducts, IsDesignTimeCreatable=True}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<toolkit:NavigationBar Content="Products" />
<Grid d:DataContext="{d:DesignInstance fake:FakeProducts, IsDesignTimeCreatable=True}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<toolkit:NavigationBar Content="Products" />
<ScrollViewer d:DataContext="{Binding Products[2]}"
DataContext="{Binding Product}" Grid.Row="1">
<StackPanel Margin="12">
<Border Height="300">
<Image Source="{Binding Photo}" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="UniformToFill" />
</Border>
<TextBlock Text="{Binding Name}" FontSize="32" FontWeight="Bold" Margin="12"/>
<Grid>
<TextBlock Text="{Binding Category}" />
<TextBlock Text="{Binding Price}" HorizontalAlignment="Right" Foreground="Red" />
</Grid>
<reactive:FeedView
Source="{Binding Product}"
Style="{StaticResource SingleStateFeedView}"
Grid.Row="1">
<DataTemplate>
<ScrollViewer
d:DataContext="{Binding Products[2]}"
DataContext="{Binding Data}">
<StackPanel Margin="12">
<Border Height="300">
<Image Source="{Binding Photo}" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="UniformToFill" />
</Border>
<Border Height="1"
Background="DarkGray" />
<TextBlock Text="{Binding Name}" FontSize="32" FontWeight="Bold" Margin="12"/>
<Grid>
<TextBlock Text="{Binding Category}" />
<TextBlock Text="{Binding Price}" HorizontalAlignment="Right" Foreground="Red" />
</Grid>
<Button Content="ADD TO CART"
HorizontalAlignment="Stretch" />
<Border Height="1" Background="DarkGray" />
<Button Content="SAVE TO FAVORITES"
HorizontalAlignment="Stretch" />
<Button Content="ADD TO CART" HorizontalAlignment="Stretch" />
<Border Height="1"
Background="DarkGray" />
<Button Content="SAVE TO FAVORITES" HorizontalAlignment="Stretch" />
<TextBlock Text="Product details"
FontWeight="Bold" />
<TextBlock Text="{Binding Description}" />
<Border Height="1" Background="DarkGray" />
<TextBlock Text="Reviews"
FontWeight="Bold" />
<TextBlock Text="Product details" FontWeight="Bold" />
<TextBlock Text="{Binding Description}" />
<controls:ItemsRepeater ItemsSource="{Binding Reviews}">
<controls:ItemsRepeater.ItemTemplate>
<DataTemplate>
<Grid Margin="4" Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Ellipse Margin="4" Fill="DarkGray" HorizontalAlignment="Left" VerticalAlignment="Center" Height="40" Width="40"/>
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<TextBlock Text="{Binding Message}" />
</StackPanel>
</Grid>
</DataTemplate>
</controls:ItemsRepeater.ItemTemplate>
</controls:ItemsRepeater>
<TextBlock Text="Reviews" FontWeight="Bold" />
</StackPanel>
</ScrollViewer>
</Grid>
<controls:ItemsRepeater ItemsSource="{Binding Reviews}">
<controls:ItemsRepeater.ItemTemplate>
<DataTemplate>
<Grid Margin="4" Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Ellipse Margin="4" Fill="DarkGray" HorizontalAlignment="Left" VerticalAlignment="Center" Height="40" Width="40"/>
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<TextBlock Text="{Binding Message}" />
</StackPanel>
</Grid>
</DataTemplate>
</controls:ItemsRepeater.ItemTemplate>
</controls:ItemsRepeater>
</StackPanel>
</ScrollViewer>
</DataTemplate>
</reactive:FeedView>
</Grid>
</Page>

Просмотреть файл

@ -1,70 +1,99 @@
<Page x:Class="Commerce.ProductsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Commerce"
xmlns:fake="using:Commerce.DesignTime"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:services="using:Commerce.Services"
xmlns:nav="using:Uno.Extensions.Navigation.Controls"
xmlns:toolkit="using:Uno.UI.ToolkitLib"
mc:Ignorable="d fake"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Commerce"
xmlns:fake="using:Commerce.DesignTime"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:services="using:Commerce.Services"
xmlns:nav="using:Uno.Extensions.Navigation.Controls"
xmlns:toolkit="using:Uno.UI.ToolkitLib"
xmlns:reactive="using:Uno.Extensions.Reactive"
mc:Ignorable="d fake"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid d:DataContext="{d:DesignInstance fake:FakeProducts, IsDesignTimeCreatable=True}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid d:DataContext="{d:DesignInstance fake:FakeProducts, IsDesignTimeCreatable=True}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<toolkit:NavigationBar Content="Products" />
<StackPanel Grid.Row="1">
<TextBox PlaceholderText="Search" />
<Grid>
<TextBlock Text="5254 Products"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="32" />
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right">
<TextBlock Text="{Binding FilterQuery}" />
<HyperlinkButton Content="Filter"
nav:Navigation.Request="!FilterPopup"
nav:Navigation.Data="{Binding FilterQuery, Mode=TwoWay}" />
</StackPanel>
</Grid>
</StackPanel>
<ListView nav:Navigation.Request="ProductDetails"
ItemsSource="{Binding Products}"
Grid.Row="2"
IsItemClickEnabled="True"
>
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="8"
Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border>
<Image Source="{Binding Photo}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="UniformToFill" />
</Border>
<StackPanel Grid.Column="1"
Margin="8">
<TextBlock Text="{Binding Name}"
FontSize="24"
FontWeight="Bold" />
<TextBlock Text="{Binding Price}"
FontSize="18" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
<toolkit:NavigationBar Content="Products" />
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<TextBox
Grid.Row="0"
PlaceholderText="Search"
Text="{Binding SearchTerm, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<reactive:FeedView
Grid.Row="1"
Undefined="Type some text to search products."
None="No products found."
Source="{Binding Items}">
<DataTemplate>
<ListView
nav:Navigation.Request="ProductDetails"
ItemsSource="{Binding Data}"
Grid.Row="2"
IsItemClickEnabled="True">
<ListView.Header>
<Grid>
<TextBlock
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="32" >
<Run Text="{Binding Data.Length}" />
<Run Text=" Products" />
</TextBlock>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Right">
<TextBlock Text="{Binding Parent.FilterQuery}" />
<HyperlinkButton
Content="Filter"
nav:Navigation.Request="!FilterPopup"
nav:Navigation.Data="{Binding Parent.FilterQuery, Mode=TwoWay}" />
</StackPanel>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<Grid
Margin="8"
Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border>
<Image
Source="{Binding Photo}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="UniformToFill" />
</Border>
<StackPanel
Grid.Column="1"
Margin="8">
<TextBlock
Text="{Binding Name}"
FontSize="24"
FontWeight="Bold" />
<TextBlock
Text="{Binding Price}"
FontSize="18" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</reactive:FeedView>
</Grid>
</Grid>
</Page>

Просмотреть файл

@ -27,6 +27,7 @@
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="6.0.0" />
<PackageReference Include="System.Linq.Async" Version="4.0.0" />
<PackageReference Include="Uno.UI.Toolkit" Version="0.1.0-dev.71" />
</ItemGroup>
<PropertyGroup>
@ -177,6 +178,14 @@
<Project>{5123670c-9756-4c9e-9844-f4a9c0aee633}</Project>
<Name>Uno.Extensions.Serialization</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Uno.Extensions.Reactive\Uno.Extensions.Reactive.csproj">
<Project>{74D93A0B-42F9-45A6-8AC3-684DAE9659A8}</Project>
<Name>Uno.Extensions.Reactive</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Uno.Extensions.Reactive.View\Uno.Extensions.Reactive.View.csproj">
<Project>{7516C1F2-6CCB-4B59-91B7-E6D4B4EA5835}</Project>
<Name>Uno.Extensions.Reactive.View</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
@ -196,6 +205,7 @@
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
<Content Include="Properties\Default.rd.xml" />
</ItemGroup>
<ItemGroup />
<Import Project="..\Commerce.Shared\Commerce.Shared.projitems" Label="Shared" />
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
@ -208,4 +218,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

Просмотреть файл

@ -55,6 +55,7 @@
<PackageReference Include="Uno.UI.RemoteControl" Version="4.0.0-dev.5489" Condition="'$(Configuration)'=='Debug'" />
<PackageReference Include="Uno.Wasm.Bootstrap" Version="3.0.0" />
<PackageReference Include="Uno.Wasm.Bootstrap.DevServer" Version="3.0.0" />
<PackageReference Include="System.Linq.Async" Version="4.0.0" />
<PackageReference Include="Uno.UI.Toolkit">
<Version>0.1.0-dev.71</Version>
</PackageReference>
@ -74,6 +75,14 @@
<ProjectReference Include="..\..\..\src\Uno.Extensions.Logging.Wasm\Uno.Extensions.Logging.Wasm.csproj" />
<ProjectReference Include="..\..\..\src\Uno.Extensions.Navigation\Uno.Extensions.Navigation.csproj" />
<ProjectReference Include="..\..\..\src\Uno.Extensions.Serialization\Uno.Extensions.Serialization.csproj" />
<ProjectReference Include="..\..\..\src\Uno.Extensions.Reactive\Uno.Extensions.Reactive.csproj">
<Project>{74D93A0B-42F9-45A6-8AC3-684DAE9659A8}</Project>
<Name>Uno.Extensions.Reactive</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Uno.Extensions.Reactive.View\Uno.Extensions.Reactive.View.csproj">
<Project>{7516C1F2-6CCB-4B59-91B7-E6D4B4EA5835}</Project>
<Name>Uno.Extensions.Reactive.View</Name>
</ProjectReference>
</ItemGroup>
<Import Project="..\Commerce.Shared\Commerce.Shared.projitems" Label="Shared" Condition="Exists('..\Commerce.Shared\Commerce.Shared.projitems')" />
</Project>
</Project>

Просмотреть файл

@ -127,6 +127,7 @@
<!--<PackageReference Include="Uno.UI.RemoteControl" Version="4.0.0-dev.5441" Condition="'$(Configuration)'=='Debug'" />-->
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Uno.Extensions.Logging.OSLog " Version="1.3.0-dev.1" />
<PackageReference Include="System.Linq.Async" Version="4.0.0" />
<PackageReference Include="Uno.UI.Toolkit" Version="0.1.0-dev.71" />
<PackageReference Include="Uno.Material" Version="1.1.0-dev.5" />
</ItemGroup>
@ -219,6 +220,14 @@
<Project>{5123670c-9756-4c9e-9844-f4a9c0aee633}</Project>
<Name>Uno.Extensions.Serialization</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Uno.Extensions.Reactive\Uno.Extensions.Reactive.csproj">
<Project>{74D93A0B-42F9-45A6-8AC3-684DAE9659A8}</Project>
<Name>Uno.Extensions.Reactive</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Uno.Extensions.Reactive.View\Uno.Extensions.Reactive.View.csproj">
<Project>{7516C1F2-6CCB-4B59-91B7-E6D4B4EA5835}</Project>
<Name>Uno.Extensions.Reactive.View</Name>
</ProjectReference>
</ItemGroup>
<Import Project="XamarinForms.targets" Condition="'$(Configuration)'=='Debug'" />
<Import Project="..\Commerce.Shared\Commerce.Shared.projitems" Label="Shared" />
@ -228,4 +237,4 @@
<UserProperties XamarinHotReloadDebuggerTimeoutExceptionCommerceiOSHideInfoBar="True" />
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>