[XmlRoot("ArrayOfBook", Namespace = "http://schemas.datacontract.org/2004/07/WcfService4")]
public class XmlBook
{
[XmlElement(nameof(Book))]
public List<Book> BksList { get; set; }
}
private List<Book> DeserializeXmlStrToList(string xmlStr)
{
var xmlSerializer = new XmlSerializer(typeof(XmlBook));
using (var reader = new StringReader(xmlStr))
{
var bks = (XmlBook)xmlSerializer.Deserialize(reader);
return bks.BksList;
}
}
<Window x:Class="WpfApp8.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:WpfApp8"
mc:Ignorable="d"
Title="MainWindow"
WindowState="Maximized">
<Window.DataContext>
<local:MainVM/>
</Window.DataContext>
<Window.Resources>
<Style TargetType="TextBlock" x:Key="TbkStyle">
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="Normal"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate DataType="{x:Type local:Book}"
x:Key="BookDataTemplate">
<Border BorderBrush="Cyan"
BorderThickness="1"
Margin="5">
<Grid Margin="5">
<Grid.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource TbkStyle}"/>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="100" SharedSizeGroup="Id"/>
<ColumnDefinition MinWidth="100" SharedSizeGroup="Name"/>
<ColumnDefinition Width="*" SharedSizeGroup="ISBN"/>
<ColumnDefinition MinWidth="100" SharedSizeGroup="Author"/>
<ColumnDefinition MinWidth="100" SharedSizeGroup="Comment"/>
<ColumnDefinition MinWidth="100" SharedSizeGroup="CategoryName"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Id}" Grid.Column="0"/>
<TextBlock Text="{Binding Name}" Grid.Column="1"/>
<TextBlock Text="{Binding ISBN}" Grid.Column="2"/>
<TextBlock Text="{Binding Author}" Grid.Column="3"/>
<TextBlock Text="{Binding Comment}" Grid.Column="4"/>
<TextBlock Text="{Binding CategoryName}" Grid.Column="5"/>
</Grid>
</Border>
</DataTemplate>
<ControlTemplate TargetType="ContentControl" x:Key="ContentControlTemplate">
<ListBox Grid.IsSharedSizeScope="True"
ItemsSource="{Binding BksCollection}"
ItemTemplate="{StaticResource BookDataTemplate}"/>
</ControlTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<GroupBox Header="ContentControlTemplate"
FontSize="30"
Grid.Row="0"
Margin="10"
BorderBrush="Blue"
BorderThickness="5">
<ContentControl Template="{StaticResource ContentControlTemplate}"
Margin="5"/>
</GroupBox>
<GroupBox Header="ListBox"
FontSize="30"
Grid.Row="1"
Margin="10"
BorderBrush="Blue"
BorderThickness="5">
<ListBox ItemsSource="{Binding BksCollection}" Grid.IsSharedSizeScope="True"
Margin="10">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:Book}">
<Border BorderBrush="Cyan"
BorderThickness="1"
Margin="5">
<Grid>
<Grid.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource TbkStyle}"/>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="100" SharedSizeGroup="Id"/>
<ColumnDefinition MinWidth="100" SharedSizeGroup="Name"/>
<ColumnDefinition Width="*" SharedSizeGroup="ISBN"/>
<ColumnDefinition MinWidth="100" SharedSizeGroup="Author"/>
<ColumnDefinition MinWidth="100" SharedSizeGroup="Comment"/>
<ColumnDefinition MinWidth="100" SharedSizeGroup="CategoryName"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Id}" Grid.Column="0"/>
<TextBlock Text="{Binding Name}" Grid.Column="1"/>
<TextBlock Text="{Binding ISBN}" Grid.Column="2"/>
<TextBlock Text="{Binding Author}" Grid.Column="3"/>
<TextBlock Text="{Binding Comment}" Grid.Column="4"/>
<TextBlock Text="{Binding CategoryName}" Grid.Column="5"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
<GroupBox Header="ListView"
Grid.Row="2"
FontSize="30"
BorderBrush="Blue"
BorderThickness="10">
<ListView ItemsSource="{Binding BksCollection}">
<ListView.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource TbkStyle}"/>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}" Width="Auto"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="Auto"/>
<GridViewColumn Header="ISBN" DisplayMemberBinding="{Binding ISBN}" Width="Auto"/>
<GridViewColumn Header="Author" DisplayMemberBinding="{Binding Author}" Width="100"/>
<GridViewColumn Header="Comment" DisplayMemberBinding="{Binding Comment}" Width="100"/>
<GridViewColumn Header="Category" DisplayMemberBinding="{Binding CategoryName}" Width="100"/>
</GridView>
</ListView.View>
</ListView>
</GroupBox>
</Grid>
</Window>
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
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 System.Xml.Serialization;
namespace WpfApp8
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class MainVM : INotifyPropertyChanged
{
private static HttpClient client = new HttpClient();
private static string originUrl = "http://localhost:64660/BookService.svc/getbooks?cnt=";
public MainVM()
{
if(!DesignerProperties.GetIsInDesignMode(new DependencyObject()))
{
_ = InitBksAsync();
}
}
private async Task InitBksAsync(int cnt=10000)
{
string url = $"{originUrl}{cnt}";
string xmlStr = await client.GetStringAsync(url);
var bks = DeserializeXmlStrToList(xmlStr);
BksCollection = new ObservableCollection<Book>(bks);
}
private List<Book> DeserializeXmlStrToList(string xmlStr)
{
var xmlSerializer = new XmlSerializer(typeof(XmlBook));
using (var reader = new StringReader(xmlStr))
{
var bks = (XmlBook)xmlSerializer.Deserialize(reader);
return bks.BksList;
}
}
private ObservableCollection<Book> bksCollection;
public ObservableCollection<Book> BksCollection
{
get
{
return bksCollection;
}
set
{
if (value != bksCollection)
{
bksCollection = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var handler = Volatile.Read(ref PropertyChanged);
if (handler == null)
{
return;
}
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
[XmlRoot("ArrayOfBook", Namespace = "http://schemas.datacontract.org/2004/07/WcfService4")]
public class XmlBook
{
[XmlElement(nameof(Book))]
public List<Book> BksList { get; set; }
}
public class Book
{
public long Id { get; set; }
public string Name { get; set; }
public string ISBN { get; set; }
public string Author { get; set; }
public string Comment { get; set; }
public string CategoryName { get; set; }
}
}
//WCF
//D:\C\WcfService4\WcfService4\IBookService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService4
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IBookService" in both code and config file together.
[ServiceContract]
public interface IBookService
{
[OperationContract]
[WebGet(UriTemplate ="/getbooks?cnt={cnt}")]
List<Book> GetBooks(int cnt=1000);
}
public class Book
{
public long Id { get; set; }
public string Name { get; set; }
public string ISBN { get; set; }
public string Author { get; set; }
public string Comment { get; set; }
public string CategoryName { get; set; }
}
enum BookCategoryEnum
{
Science,
Technology,
Engineering,
Math
}
}
//D:\C\WcfService4\WcfService4\BookService.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Threading;
namespace WcfService4
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "BookService" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select BookService.svc or BookService.svc.cs at the Solution Explorer and start debugging.
public class BookService : IBookService
{
private static long id = 1;
private static string[] enumNames = Enum.GetNames(typeof(BookCategoryEnum));
private static int enumNamesCnt = enumNames.Length;
private static Random rnd = new Random();
private static (long, long) GetStartEnd(int cnt)
{
var end = Interlocked.Add(ref id, cnt);
var start = end - cnt;
return (start, end);
}
public List<Book> GetBooks(int cnt = 1000)
{
List<Book> bksList = new List<Book>();
var (start, end) = GetStartEnd(cnt);
for (long i = start; i < end; i++)
{
bksList.Add(new Book()
{
Id = i,
Name = $"Name_{i}",
ISBN = $"ISBN_{i}_{Guid.NewGuid():N}",
Author = $"Author_{i}",
Comment = $"Comment_{i}",
CategoryName = $"{enumNames[rnd.Next(0, enumNamesCnt)]}"
});
}
return bksList;
}
}
}
//D:\C\WcfService4\WcfService4\Web.config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<!--
For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.
The following attributes can be set on the <httpRuntime> tag.
<system.Web>
<httpRuntime targetFramework="4.8.1" />
</system.Web>
-->
<system.web>
<compilation debug="true" targetFramework="4.8.1"/>
<httpRuntime targetFramework="4.7.2"/>
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="BookServiceWebHttpBinding"
openTimeout="01:00:00"
closeTimeout="01:00:00"
sendTimeout="01:00:00"
receiveTimeout="01:00:00"
maxBufferPoolSize="2147483647"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxArrayLength="2147483647"
maxBytesPerRead="214748347"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647"/>
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="BookServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="BookServiceEndPointBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<services>
<service name="WcfService4.BookService"
behaviorConfiguration="BookServiceBehavior">
<endpoint address=""
binding="webHttpBinding"
contract="WcfService4.IBookService"
behaviorConfiguration="BookServiceEndPointBehavior"
bindingConfiguration="BookServiceWebHttpBinding"/>
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
![image]()