怎么用WPF实现微信公众号多客服功能
这篇文章给大家分享的是有关怎么用WPF实现微信公众号多客服功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
原文标题:用WPF实现微信公众号多客服功能
简介:
这是利用WPF作为前端技术,实现桌面版微信多客服系统。项目采用Prism作为前端框架,采用MVVM模式极好的对UI和逻辑代码分离,使用MefBootstrapper集成的MEF IOC容器,解耦各模块对象。合理利用 IEventAggregator 实现事件和交互。文章在介绍对应功能时候会给出相关实现的参考,读者可以参考改进,引入到自己的项目中。
程序运行界面及功能预览:
一、登陆:
功能:支持记住用户和用户设置,可选择记住用户密码。
实现相关:
自定义登陆窗口,引入Microsoft.Windows.Shell。可参考 WPF Custom Chrome Library 和 MSDN WindowChrome Class 有相关自定义窗口实现。
最小化、最大化、关闭按钮功能实现可参考上面的例子。
登陆按钮,自定义Style,重写Button的Template,参考代码如下:
<Stylex:Key="LogginButton"TargetType="{x:TypeButton}"> <SetterProperty="Template"> <Setter.Value> <ControlTemplateTargetType="{x:TypeButton}"> <Grid> <Borderx:Name="Bd"Background="{TemplateBindingBackground}"BorderBrush="#d3d3d3"BorderThickness="1"> </Border> <ContentPresenterx:Name="contentPresenter"HorizontalAlignment="{TemplateBindingHorizontalContentAlignment}"VerticalAlignment="{TemplateBindingVerticalContentAlignment}"SnapsToDevicePixels="{TemplateBindingSnapsToDevicePixels}"RecognizesAccessKey="True"/> </Grid> <ControlTemplate.Triggers> <TriggerProperty="IsMouseOver"Value="True"> <SetterTargetName="Bd"Property="BorderBrush"Value="#08bd14"/> <SetterTargetName="Bd"Property="Opacity"Value="0.8"/> </Trigger> <TriggerProperty="IsPressed"Value="True"> <SetterTargetName="Bd"Property="Background"Value="#f3f3f3"/> <SetterTargetName="contentPresenter"Property="Margin"Value="2,2,0,0"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
View Code
记住密码,采用 XmlSerializer 把用户信息序列化到本地xml配置文件中,程序启动时加载该xml配置文件。用法 MSDN XmlSerializer
二、聊天窗口,信息发送
功能:文字发送,表情发送,图片发送,屏幕截图,快捷回复
RichTextBox 相关实现:文字,表情,图片所有输入都是在富文本框 里实现,因此针对 TextChanged 事件对输入进行一系列处理。
文字:不用做任何处理。
表情:文本框里输入的是表情的转义符号,然后根据转义符号找到对应表情图片进行替换。InlineUIContainer
Gif 动态图:WPF中不支持Gif,所以要编写自定义用户控件作为用来显示gif表情。参考 周银辉 [WPF疑难]在WPF中显示动态GIF
截图功能:源码在网上找到的,是Winform的一个截图。做了小许修改引进到项目。
参考:C# 实现完整功能的截图控件(4)-完整版 http://www.php.cn/
三、客户列表
控件为 TabControl,重写了TabControl 的Style 和 TabItem的Style
<Stylex:Key="CustomerTabStyle"TargetType="{x:TypeTabControl}"> <SetterProperty="Foreground"Value="{DynamicResource{x:StaticSystemColors.ControlTextBrushKey}}"/> <SetterProperty="Padding"Value="4,4,4,4"/> <SetterProperty="Background"Value="#F9F9F9"/> <SetterProperty="HorizontalContentAlignment"Value="Center"/> <SetterProperty="VerticalContentAlignment"Value="Center"/> <SetterProperty="Template"> <Setter.Value> <ControlTemplateTargetType="{x:TypeTabControl}"> <GridClipToBounds="true"SnapsToDevicePixels="true"KeyboardNavigation.TabNavigation="Local"> <Grid.ColumnDefinitions> <ColumnDefinitionx:Name="ColumnDefinition0"/> <ColumnDefinitionx:Name="ColumnDefinition1"Width="0"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinitionx:Name="RowDefinition0"Height="Auto"/> <RowDefinitionx:Name="RowDefinition1"Height="*"/> </Grid.RowDefinitions> <TabPanelx:Name="HeaderPanel"Grid.Column="0"Background="#f6f6f6"IsItemsHost="true"Grid.Row="0"KeyboardNavigation.TabIndex="1"Panel.ZIndex="1"/> <Borderx:Name="ContentPanel"Background="{TemplateBindingBackground}"Grid.Column="0"KeyboardNavigation.DirectionalNavigation="Contained"Grid.Row="1"KeyboardNavigation.TabIndex="2"KeyboardNavigation.TabNavigation="Local"> <ContentPresenterx:Name="PART_SelectedContentHost"ContentSource="SelectedContent"SnapsToDevicePixels="{TemplateBindingSnapsToDevicePixels}"/> </Border> </Grid> <ControlTemplate.Triggers> <TriggerProperty="IsEnabled"Value="false"> <SetterProperty="Foreground"Value="{DynamicResource{x:StaticSystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Stylex:Key="ConnectedTabItemStyle"TargetType="{x:TypeTabItem}"> <SetterProperty="Foreground"Value="Black"/> <SetterProperty="Padding"Value="20,8,20,0"/> <SetterProperty="BorderBrush"Value="Transparent"/> <SetterProperty="Background"Value="#b9c0cc"/> <SetterProperty="HorizontalContentAlignment"Value="Stretch"/> <SetterProperty="VerticalContentAlignment"Value="Stretch"/> <SetterProperty="Template"> <Setter.Value> <ControlTemplateTargetType="{x:TypeTabItem}"> <GridSnapsToDevicePixels="true"> <Borderx:Name="Bd"Background="#f6f6f6"Padding="{TemplateBindingPadding}"> <StackPanel> <PathWidth="18"Height="18"Stretch="Fill"Fill="{TemplateBindingBackground}"Data="F1M38,19C43.5417,1945.9167,22.166745.1174,28.8134C45.8315,29.222946.3125,29.992846.3125,30.875C46.3125,31.954545.5923,32.865844.6061,33.1546C44.1941,34.62343.5543,35.922942.75,36.9628L42.75,41.9583C45.3889,42.486147.5,42.7550.6667,44.3333C53.8333,45.916754.8889,47.368157,49.4792L57,57L19,57L19,49.4792C21.1111,47.368122.1667,45.916725.3333,44.3333C28.5,42.7530.6111,42.486133.25,41.9583L33.25,36.9628C32.4457,35.922931.8059,34.62331.3939,33.1546C30.4077,32.865829.6875,31.954529.6875,30.875C29.6875,29.992830.1685,29.222930.8826,28.8134C30.0833,22.166732.4583,1938,19Z"/> <BorderHorizontalAlignment="Center"x:Name="BottomBd"Margin="-6,-6,0,0"Visibility="Hidden"> <PathFill="#e1e1e1"Data="M7.41,15.41L12,10.83L16.59,15.41L18,14L12,8L6,14L7.41,15.41Z"/> </Border> </StackPanel> </Border> </Grid> <ControlTemplate.Triggers> <TriggerProperty="IsMouseOver"Value="true"> <SetterProperty="Background"TargetName="Bd"Value="#ededef"/> </Trigger> <TriggerProperty="IsSelected"Value="true"> <SetterProperty="Panel.ZIndex"Value="1"/> <SetterProperty="Background"TargetName="Bd"Value="#ffffff"/> <SetterProperty="Background"Value="#08bd14"/> <SetterProperty="Visibility"TargetName="BottomBd"Value="Visible"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <ConditionProperty="IsSelected"Value="false"/> <ConditionProperty="IsMouseOver"Value="true"/> </MultiTrigger.Conditions> <SetterProperty="BorderBrush"TargetName="Bd"Value="#ffffff"/> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
View Code
四、快捷回复面板
应用 TreeView 加 HierarchicalDataTemplate 实现树形列表。
五、转接客户
自定义转接客户窗口,样式Xaml代码如下:
<Stylex:Key="NoResize_Window"TargetType="{x:TypeWindow}"> <SetterProperty="FontFamily"Value="Consolas,MicrosoftYaHei"/> <SetterProperty="ResizeMode"Value="CanMinimize"/> <SetterProperty="Template"> <Setter.Value> <ControlTemplateTargetType="{x:TypeWindow}"> <Grid> <Grid.RowDefinitions> <RowDefinitionHeight="30"/> <RowDefinitionHeight="*"/> </Grid.RowDefinitions> <BorderGrid.Row="0"> <Border.Background> <LinearGradientBrushStartPoint="0,0"EndPoint="0,1"> <GradientStopColor="#494A52"Offset="0"/> <GradientStopColor="#45464f"Offset="1"/> </LinearGradientBrush> </Border.Background> <Grid> <!--IconandTitle--> <DockPanel> <TextBlockMargin="12,0,0,0"Text="{TemplateBindingTitle}"FontFamily="Calibri"VerticalAlignment="Center"Foreground="#FFFFFF"/> <StackPanelHorizontalAlignment="Right"Orientation="Horizontal"VerticalAlignment="Top"> <ctrl:MinAndCloseCaptionButton></ctrl:MinAndCloseCaptionButton> </StackPanel> </DockPanel> </Grid> </Border> <GridGrid.Row="1"> <BorderBackground="{TemplateBindingBackground}" BorderBrush="{TemplateBindingBorderBrush}" BorderThickness="{TemplateBindingBorderThickness}" Padding="{TemplateBindingMargin}" SnapsToDevicePixels="{TemplateBindingSnapsToDevicePixels}"> <ContentPresenter/> </Border> </Grid> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
View Code
转接客户列表,样式Xaml代码如下:
<Stylex:Key="OnlineUserListBoxStyle"TargetType="{x:TypeListBox}"> <SetterProperty="Background"Value="{DynamicResource{x:StaticSystemColors.WindowBrushKey}}"/> <SetterProperty="Foreground"Value="{DynamicResource{x:StaticSystemColors.ControlTextBrushKey}}"/> <SetterProperty="ScrollViewer.HorizontalScrollBarVisibility"Value="Auto"/> <SetterProperty="ScrollViewer.VerticalScrollBarVisibility"Value="Auto"/> <SetterProperty="ScrollViewer.CanContentScroll"Value="true"/> <SetterProperty="ScrollViewer.PanningMode"Value="Both"/> <SetterProperty="Stylus.IsFlicksEnabled"Value="False"/> <SetterProperty="VerticalContentAlignment"Value="Center"/> <SetterProperty="Template"> <Setter.Value> <ControlTemplateTargetType="{x:TypeListBox}"> <Borderx:Name="Bd"BorderBrush="{TemplateBindingBorderBrush}"BorderThickness="{TemplateBindingBorderThickness}"Background="{TemplateBindingBackground}"Padding="1"SnapsToDevicePixels="true"> <DockPanel> <BorderBorderBrush="#dbdbdb"BorderThickness="0,0,0,1"DockPanel.Dock="Top"> <GridBackground="#f6f6f6"TextElement.Foreground="#999999"DockPanel.Dock="Top"> <Grid.ColumnDefinitions> <ColumnDefinitionWidth="*"/> <ColumnDefinitionWidth="*"/> <ColumnDefinitionWidth="*"/> </Grid.ColumnDefinitions> <TextBlockMargin="5,7,0,6"Grid.Column="0">状态</TextBlock> <TextBlockMargin="5,7,0,6"Grid.Column="1">工号</TextBlock> <TextBlockMargin="5,7,0,6"Grid.Column="2">昵称</TextBlock> </Grid> </Border> <ScrollViewerFocusable="false"Padding="{TemplateBindingPadding}"> <ItemsPresenterSnapsToDevicePixels="{TemplateBindingSnapsToDevicePixels}"/> </ScrollViewer> </DockPanel> </Border> <ControlTemplate.Triggers> <TriggerProperty="IsEnabled"Value="false"> <SetterProperty="Background"TargetName="Bd"Value="{DynamicResource{x:StaticSystemColors.ControlBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Stylex:Key="OnlineUserListBoxItemStyle"TargetType="{x:TypeListBoxItem}"> <SetterProperty="Background"Value="Transparent"/> <SetterProperty="HorizontalContentAlignment"Value="{BindingHorizontalContentAlignment,RelativeSource={RelativeSourceAncestorType={x:TypeItemsControl}}}"/> <SetterProperty="VerticalContentAlignment"Value="{BindingVerticalContentAlignment,RelativeSource={RelativeSourceAncestorType={x:TypeItemsControl}}}"/> <SetterProperty="Padding"Value="2,0,0,0"/> <SetterProperty="Template"> <Setter.Value> <ControlTemplateTargetType="{x:TypeListBoxItem}"> <Borderx:Name="Bd"BorderBrush="{TemplateBindingBorderBrush}"BorderThickness="{TemplateBindingBorderThickness}"Background="{TemplateBindingBackground}"Padding="{TemplateBindingPadding}"SnapsToDevicePixels="true"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinitionWidth="*"/> <ColumnDefinitionWidth="*"/> <ColumnDefinitionWidth="*"/> </Grid.ColumnDefinitions> <StackPanelGrid.Column="0"Orientation="Horizontal"> <BorderMargin="4,2,4,2"Height="24"Width="24"> <Grid> <PathFill="#6f6f6f"Data="M6,17C6,1510,13.912,13.9C14,13.918,1518,17V18H6M15,9A3,300,112,12A3,300,19,9A3,300,112,6A3,300,115,9M3,5V19A2,200,05,21H19A2,200,021,19V5A2,200,019,3H5C3.89,33,3.93,5Z"/> <PathVisibility="{BindingPath=IsOnLine,Converter={StaticResourceBoolToVisibilityConverter}}"Fill="#8bc34a"Data="M6,17C6,1510,13.912,13.9C14,13.918,1518,17V18H6M15,9A3,300,112,12A3,300,19,9A3,300,112,6A3,300,115,9M3,5V19A2,200,05,21H19A2,200,021,19V5A2,200,019,3H5C3.89,33,3.93,5Z"/> </Grid> </Border> <TextBlockPadding="4,0,4,0"VerticalAlignment="Center"Text="{BindingPath=OnLineStatus}"/> </StackPanel> <StackPanelGrid.Column="1"Orientation="Horizontal"> <TextBlockPadding="4,0,4,0"VerticalAlignment="Center"Text="{BindingPath=Name}"/> </StackPanel> <StackPanelGrid.Column="2"Orientation="Horizontal"> <TextBlockPadding="4,0,4,0"VerticalAlignment="Center"Text="{BindingPath=RealName}"/> </StackPanel> </Grid> </Border> <ControlTemplate.Triggers> <TriggerProperty="IsSelected"Value="true"> <SetterProperty="Background"TargetName="Bd"Value="#9ea5b8"/> <SetterProperty="Foreground"Value="#ffffff"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <ConditionProperty="IsSelected"Value="false"/> <ConditionProperty="IsMouseOver"Value="true"/> </MultiTrigger.Conditions> <SetterProperty="Background"TargetName="Bd"Value="#e0e1e5"/> </MultiTrigger> <TriggerProperty="IsEnabled"Value="false"> <SetterProperty="Foreground"Value="{DynamicResource{x:StaticSystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
View Code
关于以上控件的事件与命令,引进System.Windows.Interactivity.
在Xmal中导入命名控件 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
使用代码如下:
<ListBoxMargin="12,0,12,0"BorderThickness="1" Style="{DynamicResourceOnlineUserListBoxStyle}" ItemContainerStyle="{DynamicResourceOnlineUserListBoxItemStyle}" ItemsSource="{BindingPath=AllUsers}" SelectedItem="{BindingPath=SelectedUser}" > <i:Interaction.Triggers> <i:EventTriggerEventName="SelectionChanged"> <i:InvokeCommandActionCommand="{BindingPath=UserSelectedChangedCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> </ListBox>
View Code
系统运行截图:
感谢各位的阅读!关于“怎么用WPF实现微信公众号多客服功能”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!