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


相关文章
|
17天前
|
缓存 算法 安全
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
48 12
|
2月前
|
前端开发 JavaScript 安全
C#一分钟浅谈:Blazor WebAssembly 开发
Blazor WebAssembly 是一个客户端框架,允许开发者使用C#和Razor语法构建Web应用。本文介绍了Blazor WebAssembly的基本概念、常见问题及解决方案,包括路由配置、数据绑定、异步操作、状态管理和性能优化等方面的内容,并分享了一些易错点及如何避免的方法。希望这些内容能帮助你在Blazor WebAssembly开发中少走弯路,提高开发效率。
123 51
|
18天前
|
前端开发 机器人 UED
OpenAI启动ChatGPT Projects,让你可以组织文件、分组聊天
OpenAI启动ChatGPT Projects,让你可以组织文件、分组聊天
|
1月前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
111 13
|
2月前
|
开发框架 缓存 .NET
C# 一分钟浅谈:Blazor Server 端开发
Blazor Server 是基于 ASP.NET Core 的框架,允许使用 C# 和 Razor 语法构建交互式 Web 应用。本文介绍 Blazor Server 的基本概念、快速入门、常见问题及解决方案,帮助开发者快速上手。涵盖创建应用、基本组件、数据绑定、状态管理、跨组件通信、错误处理和性能优化等内容。
80 1
|
2月前
|
缓存 C# 开发者
C# 一分钟浅谈:Blazor Server 端开发
本文介绍了 Blazor Server,一种基于 .NET 的 Web 开发模型,允许使用 C# 和 Razor 语法构建交互式 Web 应用。文章从基础概念、创建应用、常见问题及解决方案、易错点及避免方法等方面详细讲解,帮助开发者快速上手并提高开发效率。
73 2
|
2月前
|
人工智能 自然语言处理 自动驾驶
深入理解ChatGPT:下一代人工智能助手的开发与应用
【10月更文挑战第27天】本文深入探讨了ChatGPT的技术原理、开发技巧和应用场景,展示了其在语言理解和生成方面的强大能力。文章介绍了基于Transformer的架构、预训练与微调技术,以及如何定制化开发、确保安全性和支持多语言。通过实用工具如GPT-3 API和Fine-tuning as a Service,开发者可以轻松集成ChatGPT。未来,ChatGPT有望在智能家居、自动驾驶等领域发挥更大作用,推动人工智能技术的发展。
|
2月前
|
测试技术 Go C#
C#一分钟浅谈:ReSharper 插件增强开发效率
【10月更文挑战第25天】ReSharper 是 JetBrains 开发的一款 Visual Studio 插件,旨在提高 .NET 开发者的生产力。它通过代码分析、重构、导航等功能,帮助开发者避免常见错误,提升代码质量和开发效率。本文将通过具体代码案例,详细介绍 ReSharper 的常见功能及其应用。
59 1
|
2月前
|
C# Python
使用wxpython开发跨平台桌面应用,对wxpython控件实现类似C#扩展函数处理的探究
【10月更文挑战第30天】使用 `wxPython` 开发跨平台桌面应用时,可以通过创建辅助类来模拟 C# 扩展函数的功能。具体步骤包括:1. 创建辅助类 `WxWidgetHelpers`;2. 在该类中定义静态方法,如 `set_button_color`;3. 在应用中调用这些方法。这种方法提高了代码的可读性和可维护性,无需修改 `wxPython` 库即可为控件添加自定义功能。但需要注意显式调用方法和避免命名冲突。
|
3月前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
48 1