public class DelCommand : ICommand
{
private Action<object?>? syncExecute;
private readonly Func<object?, Task> asyncExecute;
private Predicate<object?>? canExecute;
public DelCommand(Action<object?>? executeValue, Predicate<object?>? canExecuteValue = null)
{
syncExecute = executeValue ?? throw new ArgumentNullException(nameof(executeValue));
canExecute = canExecuteValue;
}
public DelCommand(Func<object?, Task> asyncExecuteValue, Predicate<object?>? canExecuteValue = null)
{
asyncExecute = asyncExecuteValue ?? throw new ArgumentNullException(nameof(asyncExecuteValue));
canExecute = canExecuteValue;
}
public event EventHandler? CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public bool CanExecute(object? parameter)
{
return canExecute == null ? true : canExecute(parameter);
}
public async void Execute(object? parameter)
{
if (!CanExecute(parameter))
{
return;
}
if (asyncExecute != null)
{
await asyncExecute(parameter);
}
else if (syncExecute != null)
{
syncExecute(parameter);
}
}
}
private ICommand mouseDownCommand;
public ICommand MouseDownCommand
{
get
{
if (mouseDownCommand == null)
{
mouseDownCommand = new DelCommand(MouseDownCommandExecuted);
}
return mouseDownCommand;
}
}
private async Task MouseDownCommandExecuted(object? obj)
{
var btnEventArgs = obj as MouseButtonEventArgs;
if (btnEventArgs != null)
{
await InitBooksCollectionAsync();
string msg = $"MinId:{BooksCollection.OrderBy(x => x.Id).FirstOrDefault()?.Id}\n" +
$"MaxId:{BooksCollection.OrderByDescending(x => x.Id).FirstOrDefault()?.Id}";
MessageBox.Show($"{msg}",
$"{DateTime.Now}");
}
}
private async Task InitBooksCollectionAsync()
{
string dataUrl = "https://localhost:7146/api/book";
using (HttpClient client = new HttpClient())
{
string jsonStr = await client.GetStringAsync(dataUrl);
if (!string.IsNullOrWhiteSpace(jsonStr))
{
List<Book>? bksList = JsonConvert.DeserializeObject<List<Book>>(jsonStr);
if (bksList != null && bksList.Any())
{
BooksCollection = new ObservableCollection<Book>(bksList);
MainTitle = $"{DateTime.Now},loaded last idx:{bksList.OrderByDescending(x => x.Id).FirstOrDefault()?.Id}";
}
}
}
}
![image]()
![image]()
![image]()
//WebAPI
namespace WebApplication2.Models
{
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
public string ISBN { get; set; }
public string Comment { get; set; }
public string Content { get;set; }
public string Summary { get; set; }
public string Title { get; set; }
public string Topic { get; set; }
}
}
using WebApplication2.Models;
namespace WebApplication2.Services
{
public class BookService:IDisposable
{
int idx = 0;
private int GetIdx()
{
return Interlocked.Increment(ref idx);
}
public List<Book> GetBooksList(int cnt=10000)
{
List<Book> booksList=new List<Book>();
for(int i=0;i<cnt;i++)
{
int a=GetIdx();
booksList.Add(new Book()
{
Id = a,
Name = $"Name_{a}",
ISBN = $"ISBN_{a}_{Guid.NewGuid():N}",
Comment =$"Comment_{a}",
Content=$"Content_{a}",
Title=$"Title_{a}",
Topic=$"Topic_{a}"
});
}
return booksList;
}
public void Dispose()
{
idx = 0;
}
}
}
using Microsoft.AspNetCore.Mvc;
using WebApplication2.Models;
using WebApplication2.Services;
namespace WebApplication2.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class BookController : Controller
{
private BookService bkService;
public BookController(BookService bkServiceValue)
{
bkService= bkServiceValue;
}
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<List<Book>> GetBooksList()
{
var bksList = bkService.GetBooksList();
return Ok(bksList);
}
}
}
using WebApplication2.Services;
namespace WebApplication2
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddSingleton<BookService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
}
//WPF
<Window x:Class="WpfApp7.MainWindow"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp7"
xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
WindowState="Maximized"
Title="{Binding MainTitle}" Height="450" Width="800">
<behavior:Interaction.Triggers>
<behavior:EventTrigger EventName="MouseDown">
<behavior:InvokeCommandAction
Command="{Binding MouseDownCommand}"
PassEventArgsToCommand="True"/>
</behavior:EventTrigger>
</behavior:Interaction.Triggers>
<Window.DataContext>
<local:MainVM/>
</Window.DataContext>
<Grid>
<DataGrid ItemsSource="{Binding BooksCollection}"
IsReadOnly="True"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling"
EnableRowVirtualization="True"
EnableColumnVirtualization="True"
ScrollViewer.CanContentScroll="True"
ScrollViewer.IsDeferredScrollingEnabled="True"
VirtualizingPanel.CacheLength="2,2"
VirtualizingPanel.CacheLengthUnit="Item"
AutoGenerateColumns="True"
CanUserAddRows="False">
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<Setter Property="FontSize" Value="30"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FontSize" Value="50"/>
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<behavior:Interaction.Triggers>
<behavior:EventTrigger EventName="PreviewMouseDown">
<behavior:InvokeCommandAction
Command="{Binding MouseDownCommand}"
PassEventArgsToCommand="True"/>
</behavior:EventTrigger>
</behavior:Interaction.Triggers>
</DataGrid>
</Grid>
</Window>
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Newtonsoft.Json;
namespace WpfApp7
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class MainVM : INotifyPropertyChanged
{
public MainVM()
{
_=InitBooksCollectionAsync();
}
private ICommand mouseDownCommand;
public ICommand MouseDownCommand
{
get
{
if (mouseDownCommand == null)
{
mouseDownCommand = new DelCommand(MouseDownCommandExecuted);
}
return mouseDownCommand;
}
}
private async Task MouseDownCommandExecuted(object? obj)
{
var btnEventArgs = obj as MouseButtonEventArgs;
if (btnEventArgs != null)
{
await InitBooksCollectionAsync();
string msg = $"MinId:{BooksCollection.OrderBy(x => x.Id).FirstOrDefault()?.Id}\n" +
$"MaxId:{BooksCollection.OrderByDescending(x => x.Id).FirstOrDefault()?.Id}";
MessageBox.Show($"{msg}",
$"{DateTime.Now}");
}
}
private async Task InitBooksCollectionAsync()
{
string dataUrl = "https://localhost:7146/api/book";
using (HttpClient client = new HttpClient())
{
string jsonStr = await client.GetStringAsync(dataUrl);
if (!string.IsNullOrWhiteSpace(jsonStr))
{
List<Book>? bksList = JsonConvert.DeserializeObject<List<Book>>(jsonStr);
if (bksList != null && bksList.Any())
{
BooksCollection = new ObservableCollection<Book>(bksList);
MainTitle = $"{DateTime.Now},loaded last idx:{bksList.OrderByDescending(x => x.Id).FirstOrDefault()?.Id}";
}
}
}
}
private string mainTitle="";
public string MainTitle
{
get
{
return mainTitle;
}
set
{
if (value != mainTitle)
{
mainTitle = value;
OnPropertyChanged();
}
}
}
private ObservableCollection<Book> booksCollection;
public ObservableCollection<Book> BooksCollection
{
get
{
return booksCollection;
}
set
{
if (value != booksCollection)
{
booksCollection = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var handler = PropertyChanged;
if (handler != null)
{
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class DelCommand : ICommand
{
private Action<object?>? syncExecute;
private readonly Func<object?, Task> asyncExecute;
private Predicate<object?>? canExecute;
public DelCommand(Action<object?>? executeValue, Predicate<object?>? canExecuteValue = null)
{
syncExecute = executeValue ?? throw new ArgumentNullException(nameof(executeValue));
canExecute = canExecuteValue;
}
public DelCommand(Func<object?, Task> asyncExecuteValue, Predicate<object?>? canExecuteValue = null)
{
asyncExecute = asyncExecuteValue ?? throw new ArgumentNullException(nameof(asyncExecuteValue));
canExecute = canExecuteValue;
}
public event EventHandler? CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public bool CanExecute(object? parameter)
{
return canExecute == null ? true : canExecute(parameter);
}
public async void Execute(object? parameter)
{
if (!CanExecute(parameter))
{
return;
}
if (asyncExecute != null)
{
await asyncExecute(parameter);
}
else if (syncExecute != null)
{
syncExecute(parameter);
}
}
}
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
public string ISBN { get; set; }
public string Comment { get; set; }
public string Content { get; set; }
public string Summary { get; set; }
public string Title { get; set; }
public string Topic { get; set; }
}
}