WPF ContentControl Template

Install-Package Newtonsoft.Json

 

<Window.Resources>
    
    <DataTemplate x:Key="DGDataTemplate" 
                  DataType="{x:Type local:Book}">
        <Border BorderBrush="LightGray" 
                BorderThickness="2"
                Margin="5">
            <Grid>
                <Grid.Resources>
                    <Style TargetType="TextBlock">
                        <Setter Property="FontSize" Value="30"/>
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Foreground" Value="Red"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Grid.Resources>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0" Grid.Column="0">Id:<Run Text="{Binding Id}"/></TextBlock>
                <TextBlock Grid.Row="0" Grid.Column="1">Name:<Run Text="{Binding Name}"/></TextBlock>
                <TextBlock Grid.Row="1" Grid.Column="0">ISBN:<Run Text="{Binding ISBN}"/></TextBlock>
                <TextBlock Grid.Row="1" Grid.Column="1">CategoryName:<Run Text="{Binding CategoryName}"/></TextBlock>
                <TextBlock Grid.Row="2" Grid.Column="0">Author:<Run Text="{Binding Author}"/></TextBlock>
                <TextBlock Grid.Row="2" Grid.Column="1">Comment:<Run Text="{Binding Comment}"/></TextBlock>
                <TextBlock Grid.Row="3" Grid.Column="0">Content:<Run Text="{Binding Content}"/></TextBlock>
                <TextBlock Grid.Row="3" Grid.Column="1">Summary:<Run Text="{Binding Summary}"/></TextBlock>
                <TextBlock Grid.Row="4" Grid.Column="0">Title:<Run Text="{Binding Title}"/></TextBlock>
                <TextBlock Grid.Row="4" Grid.Column="1">Topic:<Run Text="{Binding Topic}"/></TextBlock>
            </Grid>
        </Border>
    </DataTemplate>

    <ControlTemplate x:Key="DGControlTemplate" TargetType="ContentControl">
        <DataGrid ItemsSource="{Binding Books}"
                  VirtualizingPanel.IsVirtualizing="True"
                  VirtualizingPanel.VirtualizationMode="Recycling"
                  VirtualizingPanel.CacheLength="5,5"
                  VirtualizingPanel.CacheLengthUnit="Item"
                  ScrollViewer.CanContentScroll="True"
                  ScrollViewer.IsDeferredScrollingEnabled="True"
                  AutoGenerateColumns="False"
                  CanUserAddRows="False"
                  SnapsToDevicePixels="True"
                  UseLayoutRounding="True">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <Binding Source="{StaticResource DGDataTemplate}"/>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </ControlTemplate>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ContentControl Grid.Column="0" Template="{StaticResource DGControlTemplate}" DataContext="{Binding}" 
                    Content="{Binding}"/>
    <ContentControl Grid.Column="1" Template="{StaticResource DGControlTemplate}"/>

 

 

 

 

 

 

image

 

 

 

 

image

 

 

 

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow"
        WindowState="Maximized">
    <Window.DataContext>
        <local:MainVM/>
    </Window.DataContext>
    <Window.Resources>
        
        <DataTemplate x:Key="DGDataTemplate" 
                      DataType="{x:Type local:Book}">
            <Border BorderBrush="LightGray" 
                    BorderThickness="2"
                    Margin="5">
                <Grid>
                    <Grid.Resources>
                        <Style TargetType="TextBlock">
                            <Setter Property="FontSize" Value="30"/>
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Foreground" Value="Red"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Grid.Resources>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Row="0" Grid.Column="0">Id:<Run Text="{Binding Id}"/></TextBlock>
                    <TextBlock Grid.Row="0" Grid.Column="1">Name:<Run Text="{Binding Name}"/></TextBlock>
                    <TextBlock Grid.Row="1" Grid.Column="0">ISBN:<Run Text="{Binding ISBN}"/></TextBlock>
                    <TextBlock Grid.Row="1" Grid.Column="1">CategoryName:<Run Text="{Binding CategoryName}"/></TextBlock>
                    <TextBlock Grid.Row="2" Grid.Column="0">Author:<Run Text="{Binding Author}"/></TextBlock>
                    <TextBlock Grid.Row="2" Grid.Column="1">Comment:<Run Text="{Binding Comment}"/></TextBlock>
                    <TextBlock Grid.Row="3" Grid.Column="0">Content:<Run Text="{Binding Content}"/></TextBlock>
                    <TextBlock Grid.Row="3" Grid.Column="1">Summary:<Run Text="{Binding Summary}"/></TextBlock>
                    <TextBlock Grid.Row="4" Grid.Column="0">Title:<Run Text="{Binding Title}"/></TextBlock>
                    <TextBlock Grid.Row="4" Grid.Column="1">Topic:<Run Text="{Binding Topic}"/></TextBlock>
                </Grid>
            </Border>
        </DataTemplate>

        <ControlTemplate x:Key="DGControlTemplate" TargetType="ContentControl">
            <DataGrid ItemsSource="{Binding Books}"
                      VirtualizingPanel.IsVirtualizing="True"
                      VirtualizingPanel.VirtualizationMode="Recycling"
                      VirtualizingPanel.CacheLength="5,5"
                      VirtualizingPanel.CacheLengthUnit="Item"
                      ScrollViewer.CanContentScroll="True"
                      ScrollViewer.IsDeferredScrollingEnabled="True"
                      AutoGenerateColumns="False"
                      CanUserAddRows="False"
                      SnapsToDevicePixels="True"
                      UseLayoutRounding="True">
                <DataGrid.Columns>
                    <DataGridTemplateColumn>
                        <DataGridTemplateColumn.CellTemplate>
                            <Binding Source="{StaticResource DGDataTemplate}"/>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ContentControl Grid.Column="0" Template="{StaticResource DGControlTemplate}" DataContext="{Binding}" 
                        Content="{Binding}"/>
        <ContentControl Grid.Column="1" Template="{StaticResource DGControlTemplate}"/>
        
        <!--<DataGrid ItemsSource="{Binding Books}" 
                  Grid.Column="1"
          VirtualizingPanel.IsVirtualizing="True"
          VirtualizingPanel.VirtualizationMode="Recycling"
          VirtualizingPanel.CacheLength="5,5"
          VirtualizingPanel.CacheLengthUnit="Item"
          ScrollViewer.CanContentScroll="True"
          ScrollViewer.IsDeferredScrollingEnabled="True"
          AutoGenerateColumns="False"
          CanUserAddRows="False"
          SnapsToDevicePixels="True"
          UseLayoutRounding="True">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <Binding  Source="{StaticResource DGDataTemplate}"/>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>-->
        
    </Grid>
</Window>


using Newtonsoft.Json;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json.Serialization;
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;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class MainVM : INotifyPropertyChanged
    {
        static HttpClient client = new HttpClient();
        static string originUrl = "http://localhost:51436/BookService.svc/getbooks?cnt=";
        public MainVM()
        {
            if (!DesignerProperties.GetIsInDesignMode(new DependencyObject()))
            {
                _ = InitBooksAsync(1000000);
            }
        }

        private async Task InitBooksAsync(int len)
        {
            string jsonStr = await client.GetStringAsync($"{originUrl}{len}");
            var bks = JsonConvert.DeserializeObject<List<Book>>(jsonStr);
            Books = new ObservableCollection<Book>(bks);
        }

        private ObservableCollection<Book> books;
        public ObservableCollection<Book> Books
        {
            get
            {
                return books;
            }
            set
            {
                if (value != books)
                {
                    books = value;
                    OnPropertyChanged();
                }
            }
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propName = "")
        {
            var handler = Volatile.Read(ref this.PropertyChanged);
            if (handler == null)
            {
                return;
            }
            handler.Invoke(this, new PropertyChangedEventArgs(propName));
        }
    }

    public class Book
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public string ISBN { get; set; }
        public string CategoryName { get; set; }
        public string Author { 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService1
{
    // 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}",RequestFormat =WebMessageFormat.Json,ResponseFormat =WebMessageFormat.Json)]
        List<Book> GetBooks(int cnt);
    }



    public class Book
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public string ISBN { get; set; }
        public string CategoryName { get; set; }
        public string Author { 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;  }
    }

    enum BookCategoryEnum
    {
        Science,
        Technology,
        Engineering,
        Math
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Threading;

namespace WcfService1
{
    // 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 Random rnd=new Random();
        int enumsCnt = enumNames.Count();
        private static (long,long) GetStartEnd(long interval)
        {
            long end=Interlocked.Add(ref  id, interval);
            long start = end - interval;
            return (start,end);
        }

        public List<Book> GetBooks(int cnt)
        {
            List<Book> bks = new List<Book>(cnt);
            var(start,end) = GetStartEnd(cnt);  
            for(long i=start;i<end;i++)
            {
                bks.Add(new Book()
                {
                    Id = i,
                    ISBN = $"ISBN_{i}_{Guid.NewGuid():N}",
                    CategoryName = $"{enumNames[i%enumsCnt]}",
                    Name = $"Name_{i}",
                    Author = $"Author_{i}",
                    Comment = $"Comment_{i}",
                    Content = $"Content_{i}",
                    Summary = $"Summary_{i}",
                    Title = $"Title_{i}",
                    Topic = $"Topic_{i}"
                });
            }
            return bks;
        }
    }
}


<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8"/>
  </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="2147483647"
                                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="WcfService1.BookService"
                   behaviorConfiguration="BookServiceBehavior">
              <endpoint address=""
                        binding="webHttpBinding"
                        contract="WcfService1.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>

 

posted @ 2026-07-19 21:28  FredGrit  阅读(7)  评论(0)    收藏  举报