使用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>


相关文章
|
3月前
|
XML 测试技术 API
利用C#开发ONVIF客户端和集成RTSP播放功能
利用C#开发ONVIF客户端和集成RTSP播放功能
1455 123
|
2月前
|
人工智能 JSON 前端开发
ChatGPT如何实现聊天一样的实时交互?快速读懂SSE实时“推”技术
本文将带你快速认识SSE实时通信协议,包括它的技术原理、常见使用场景、与同类技术的对比以及简单的示例代码等。
129 0
ChatGPT如何实现聊天一样的实时交互?快速读懂SSE实时“推”技术
|
7月前
|
存储 SQL 数据库连接
C#程序调用Sql Server存储过程异常处理:调用存储过程后不返回、不抛异常的解决方案
本文分析了C#程序操作Sql Server数据库时偶发的不返回、不抛异常问题,并提出了解决思路。首先解析了一个执行存储过程的函数`ExecuteProcedure`,其功能是调用存储过程并返回影响行数。针对代码执行被阻塞但无异常的情况,文章总结了可能原因,如死锁、无限循环或网络问题等。随后提供了多种解决方案:1) 增加日志定位问题;2) 使用异步操作提升响应性;3) 设置超时机制避免阻塞;4) 利用线程池分离主线程;5) 通过信号量同步线程;6) 监控数据库连接状态确保可用性。这些方法可有效应对数据库操作中的潜在问题,保障程序稳定性。
561 11
|
10月前
|
物联网 数据处理 C#
C#实现上位机开发,串口通信,读写串口数据并处理16进制数据
C#实现上位机开发,串口通信,读写串口数据并处理16进制数据。在自动化、物联网以及工业控制行业中,上位机开发是一项重要的技能。本教程主要介绍使用C#进行上位机开发,重点在于串口通信和数据处理。
1912 82
|
8月前
|
SQL 小程序 API
如何运用C#.NET技术快速开发一套掌上医院系统?
本方案基于C#.NET技术快速构建掌上医院系统,结合模块化开发理念与医院信息化需求。核心功能涵盖用户端的预约挂号、在线问诊、报告查询等,以及管理端的排班管理和数据统计。采用.NET Core Web API与uni-app实现前后端分离,支持跨平台小程序开发。数据库选用SQL Server 2012,并通过读写分离与索引优化提升性能。部署方案包括Windows Server与负载均衡设计,确保高可用性。同时针对API差异、数据库老化及高并发等问题制定应对措施,保障系统稳定运行。推荐使用Postman、Redgate等工具辅助开发,提升效率与质量。
308 0
|
10月前
|
存储 人工智能 API
ChatGPT-on-WeChat:Star32.4k, DeepSeek加持!这款开源神器秒变AI助手,聊天体验直接起飞!
嗨,大家好,我是小华同学。今天为大家介绍一款结合DeepSeek引擎的开源项目——ChatGPT-on-WeChat,由开发者zhayujie打造。它将微信变成智能AI助手,支持文本、图片、语音对话,具备定时提醒、天气查询等扩展功能,完全开源且易于定制。项目地址:https://github.com/zhayujie/chatgpt-on-wechat。关注我们,获取更多优质开源项目和高效学习方法。
1044 11
|
前端开发 JavaScript 安全
C#一分钟浅谈:Blazor WebAssembly 开发
Blazor WebAssembly 是一个客户端框架,允许开发者使用C#和Razor语法构建Web应用。本文介绍了Blazor WebAssembly的基本概念、常见问题及解决方案,包括路由配置、数据绑定、异步操作、状态管理和性能优化等方面的内容,并分享了一些易错点及如何避免的方法。希望这些内容能帮助你在Blazor WebAssembly开发中少走弯路,提高开发效率。
415 51
|
12月前
|
缓存 算法 安全
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
389 12
|
12月前
|
前端开发 机器人 UED
OpenAI启动ChatGPT Projects,让你可以组织文件、分组聊天
OpenAI启动ChatGPT Projects,让你可以组织文件、分组聊天
|
12月前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
576 13