使用C#开发ChatGPT聊天程序

简介: 最近ChatGPT比较火,大多是用python开发的,今天使用wpf来开发一款ChatGPT聊天程序

使用C#开发ChatGPT聊天程序

总体效果如下:

关键点1:无边框窗口拖动

Window中设置AllowsTransparency="True"Background="Transparent"以及WindowStyle="None"这样设置的话默认窗口的标题栏为不可见状态,且无法用鼠标拖动,使用windowChorme来解决

<WindowChrome.WindowChrome>

   <WindowChromeCaptionHeight="50"UseAeroCaptionButtons="False"/>

</WindowChrome.WindowChrome>

该设置的详细讲解参见WPF之Window无边框拖动、特殊形状、Grid拖拽

关键点2:输入栏实现删除按钮

  1. 定义TextBox的ControlTemplate模板(节取重要部分)

<Stylex:Key="TextBoxPromote"TargetType="{x:Type TextBox}">

           <SetterProperty="Template">

               <Setter.Value>

                   <ControlTemplateTargetType="{x:Type TextBox}">

                       <Border

                           x:Name="border"

                           CornerRadius="6"

                           <DockPanel LastChildFill="True">

                           <!--新增btn按钮,并绑定Click事件-->

                               <Button

                                   x:Name="btn"

                                   Grid.Column="1"

                                   Background="White"

                                   BorderThickness="0"

                                   Click="Button_Click"

                                   Content="&#xe8d5;"

                                   DockPanel.Dock="Right"

                                   FontFamily="./img/#iconfont"/>

                               <ScrollViewer

                                   x:Name="PART_ContentHost"

                                   DockPanel.Dock="Left"

                                   Focusable="false"

                                   HorizontalScrollBarVisibility="Hidden"

                                   VerticalScrollBarVisibility="Hidden"/>

                           </DockPanel>

                       </Border>

                       <ControlTemplate.Triggers>

                          <!--新增DataTrigger,当Text属性部位为空时,不显示按钮,Hiddern表示不显示,但是用空格来代替按钮来保持布局,而Collapsed则是不显示且不保留空格-->

                           <DataTriggerBinding="{Binding RelativeSource={RelativeSource Self}, Path=Text}"Value="">

                               <SetterTargetName="btn"Property="Visibility"Value="Collapsed"/>

                           </DataTrigger>

                       </ControlTemplate.Triggers>

                   </ControlTemplate>

               </Setter.Value>

           </Setter>

       </Style>

  1. 实现Button按钮事件

privatevoidButton_Click(objectsender, RoutedEventArgse)

{

   Button?btn=senderasButton;

   if (btn!=null)

   {

       varparent=VisualTreeHelper.GetParent(btn);

       while (!(parentisTextBox))

       {

           parent=VisualTreeHelper.GetParent(parent);

       }

       TextBoxtxt=parentasTextBox;

       if (txt!=null)

       {

           txt.Clear();

       }

   }

}

关键点3:ListBox实现聊天效果

本文使用ListBox来完成消息框的展示,因为涉及到发送和收到两种类型的消息,应该对应两种不同格式,所以会用到样式选择器,不知道怎么用的小伙伴可以看一下这篇文章WPF控件模板、数据模板、容器样式选择器

  1. 定义选择器类

publicclassDateTemplateSelector:DataTemplateSelector

{

   publicDataTemplateSendTemplate { get; set; }

   publicDataTemplateResTemplate { get; set; }

   publicoverrideDataTemplateSelectTemplate(objectitem, DependencyObjectcontainer)

   {

       Messagemessage= (Message)item;

       if (message.IsSend)

       {

           returnSendTemplate;

       }

       else

       {

           returnResTemplate;

       }

   }

}

  1. 在Windwo.Resources中定义数据模板

发送模板

<DataTemplatex:Key="chatSend">

   <StackPanel

       x:Name="SendMsg"

       Margin="0,12,20,0"

       HorizontalAlignment="Right"

       Orientation="Horizontal">

       <StackPanelMargin="0,0,10,0"Orientation="Vertical">

           <!--  消息内容  -->

           <Border

               MinWidth="50"

               MinHeight="30"

               MaxWidth="{Binding Path=ActualWidth,ElementName=borderWidth}"

               Background="#c8dd1f"

               BorderBrush="#ddd"

               BorderThickness="1"

               CornerRadius="8,0,8,8">

               <TextBox

                   MinWidth="30"

                   Margin="8"

                   VerticalAlignment="Center"

                   Background="Transparent"

                   BorderThickness="0"

                   FontSize="14"

                   IsReadOnly="True"

                   Text="{Binding Msg}"

                   TextWrapping="WrapWithOverflow"/>

           </Border>

       </StackPanel>

       <!--  头像  -->

       <Border

           Width="35"

           Height="35"

           Margin="0,2,0,0"

           VerticalAlignment="Top"

           BorderThickness="0">

           <Border.Background>

               <ImageBrushImageSource="/img/user.jpg"/>

           </Border.Background>

       </Border>

   </StackPanel>

</DataTemplate>

接收模板

<DataTemplatex:Key="chatRes">

   <StackPanel

       x:Name="SendMsg"

       Margin="0,12,20,0"

       HorizontalAlignment="Right"

       Orientation="Horizontal">

       <!--  头像  -->

       <Border

                   Width="35"

                   Height="35"

                   Margin="0,2,0,0"

                   VerticalAlignment="Top"

                   BorderThickness="0">

                   <Border.Background>

                       <ImageBrushImageSource="/img/图标ChatGPT.ico"/>

                   </Border.Background>

               </Border>

       <StackPanelMargin="0,0,10,0"Orientation="Vertical">

           <!--  消息内容  -->

           <Border

               MinWidth="50"

               MinHeight="30"

               MaxWidth="{Binding Path=ActualWidth,ElementName=borderWidth}"

               Background="#c8dd1f"

               BorderBrush="#ddd"

               BorderThickness="1"

               CornerRadius="0,8,8,8">

               <TextBox

                   MinWidth="30"

                   Margin="8"

                   VerticalAlignment="Center"

                   Background="Transparent"

                   BorderThickness="0"

                   FontSize="14"

                   IsReadOnly="True"

                   MaxLength="25"

                   Text="{Binding Msg}"

                   TextWrapping="WrapWithOverflow"/>

           </Border>

       </StackPanel>

   </StackPanel>

</DataTemplate>

  1. 因为发送消息和接受消息的对齐方式不同,一个是左一个是右,所以要定义下ListBox.ItemContainerStyle

<Stylex:Key="listViewItemStyle"TargetType="{x:Type ListBoxItem}">

   <SetterProperty="FocusVisualStyle"Value="{x:Null}"/>

   <SetterProperty="Template">

       <Setter.Value>

           <ControlTemplateTargetType="{x:Type ListBoxItem}">

               <Border

                   Name="Bd"

                   Margin="1"

                   Padding="{TemplateBinding Padding}"

                   Background="{TemplateBinding Background}"

                   BorderBrush="{TemplateBinding BorderBrush}"

                   BorderThickness="{TemplateBinding BorderThickness}"

                   SnapsToDevicePixels="true">

                   <ContentPresenter

                       Margin="1"

                       HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"

                       VerticalAlignment="{TemplateBinding VerticalContentAlignment}"

                       SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>

               </Border>

           </ControlTemplate>

       </Setter.Value>

   </Setter>

   <!--判断是否为发送,从而使用不同的对齐方式-->

   <Style.Triggers>

       <DataTriggerBinding="{Binding IsSend}"Value="True">

           <SetterProperty="HorizontalContentAlignment"Value="Stretch"/>

       </DataTrigger>

       <DataTriggerBinding="{Binding IsSend}"Value="False">

           <SetterProperty="HorizontalContentAlignment"Value="Left"/>

       </DataTrigger>

   </Style.Triggers>

</Style>

  1. 为了实现ListBox始终保持下拉到最后的状态,自定义类,重写OnItemsChanged方法

classScrollingListBox : ListBox

{

   protectedoverridevoidOnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgse)

   {

       if (e.NewItems==null) return;

       varnewItemCount=e.NewItems.Count;

       if (newItemCount>0)

           this.ScrollIntoView(e.NewItems[newItemCount-1]);

       base.OnItemsChanged(e);

   }

}

  1. XAML中设置

<!--  消息显示区  -->

<!--设置ScrollViewer.CanContentScroll="False"可以使得滚动条更加丝滑-->

<local:ScrollingListBox

   Grid.Row="0"

   BorderBrush="#D3D3D3"

   BorderThickness="0,1,0,1"

   ItemsSource="{Binding Path=Messages, ElementName=mainWindow}"

   ScrollViewer.HorizontalScrollBarVisibility="Disabled"

   ScrollViewer.CanContentScroll="False"

   SelectionMode="Extended">

   <ListBox.ItemTemplateSelector>

       <local:DateTemplateSelector ResTemplate="{StaticResource chatRes}" SendTemplate="{StaticResource chatSend}" />

   </ListBox.ItemTemplateSelector>

   <ListBox.ItemContainerStyle>

       <Style BasedOn="{StaticResource listViewItemStyle}" TargetType="{x:Type ListBoxItem}" />

   </ListBox.ItemContainerStyle>

</local:ScrollingListBox>


相关文章
|
8天前
|
开发框架 前端开发 .NET
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
集成于VS 2019,EXT.NET前端和ASP.NET后端,搭配MSSQL 2018数据库。系统覆盖样品管理、数据分析、报表和项目管理等实验室全流程。应用广泛,包括生产质检(如石化、制药)、环保监测、试验研究等领域。随着技术发展,现代LIMS还融合了临床、电子实验室笔记本和SaaS等功能,以满足复杂多样的实验室管理需求。
17 3
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
|
1天前
|
前端开发 测试技术 C#
如何开发一套基于C#和.NET 6.0手术麻醉系统? 手术麻醉系统源码
如何开发一套基于C#和.NET 6.0手术麻醉系统?
7 1
|
6天前
|
C#
WPF/C#:程序关闭的三种模式
WPF/C#:程序关闭的三种模式
10 3
|
12天前
|
并行计算 算法 C#
C# Mandelbrot和Julia分形图像生成程序更新到2010-9-14版 支持多线程计算 多核处理器
此文档是一个关于分形图像生成器的介绍,作者分享了个人开发的M-J算法集成及色彩创新,包括源代码和历史版本。作者欢迎有兴趣的读者留言交流,并提供了邮箱(delacroix_xu@sina.com)以分享资源。文中还展示了程序的发展历程,如增加了真彩色效果、圈选放大、历史记录等功能,并分享了几幅精美的分形图像。此外,还提到了程序的新特性,如导入ini文件批量输出图像和更新一批图片的功能。文档末尾附有多张程序生成的高分辨率分形图像示例。
|
1月前
|
存储 运维 BI
基于C#-VC-MSSQL开发的全套PACS系统源码 3D PACS系统源码:可实现医学影像获取、存档、观片、处理、打印多项应用
PACS的功能价值在于通过连接不同的影像设备,存储与管理图像,图像的调用与后处理,实现资源共享,降低成本,达到提高工作效率、提升医疗水平的目地;
29 1
基于C#-VC-MSSQL开发的全套PACS系统源码  3D PACS系统源码:可实现医学影像获取、存档、观片、处理、打印多项应用
|
26天前
|
开发框架 .NET C#
使用C#进行.NET框架开发:深入探索与实战
【5月更文挑战第28天】本文探讨了C#在.NET框架中的应用,展示了其作为强大编程语言的特性,如类型安全、面向对象编程。C#与.NET框架的结合,提供了一站式的开发环境,支持跨平台应用。文中介绍了C#的基础知识,如数据类型、控制结构和面向对象编程,以及.NET的关键技术,包括LINQ、ASP.NET和WPF。通过一个实战案例,展示了如何使用C#和ASP.NET开发Web应用,包括项目创建、数据库设计、模型和控制器编写,以及视图和路由配置。本文旨在揭示C#在.NET开发中的深度和广度,激发开发者探索更多可能性。
|
19天前
|
监控 网络协议 C#
一款基于C#开发的通讯调试工具(支持Modbus RTU、MQTT调试)
一款基于C#开发的通讯调试工具(支持Modbus RTU、MQTT调试)
|
1月前
|
SQL 存储 Oracle
C#利用IDbCommand实现通用数据库脚本执行程序
C#利用IDbCommand实现通用数据库脚本执行程序
|
30天前
|
测试技术 持续交付 C#
C#程序基础开发入门学习笔记
C#是一种现代的、面向对象的编程语言,广泛应用于Windows应用程序开发、游戏开发(尤其是Unity引擎)、Web应用程序以及跨平台应用等。
34 0
|
1月前
|
监控 安全 C#
开发公司电脑监控软件的报警系统:一个C#示例
在当今数字化时代,企业对其计算机网络和系统的安全性和稳定性越来越重视。为了确保员工遵守公司政策、保护机密信息以及监控系统的正常运行,开发一种可靠的公司电脑监控软件变得至关重要。本文将介绍如何使用C#编写一个简单而有效的报警系统,以便监控关键数据并在必要时发出警报。
95 0