WPF 實現微信公衆號多客服(效果實現篇)

 

簡介:html

  這是利用WPF做爲前端技術,實現桌面版微信多客服系統。項目採用Prism做爲前端框架,採用MVVM模式極好的對UI和邏輯代碼分離,使用MefBootstrapper集成的MEF IOC容器,解耦各模塊對象。合理利用 IEventAggregator 實現事件和交互。文章在介紹對應功能時候會給出相關實現的參考,讀者能夠參考改進,引入到本身的項目中。前端

程序運行界面及功能預覽:chrome

 

1、登錄:shell

功能:支持記住用戶和用戶設置,可選擇記住用戶密碼。express

實現相關:windows

自定義登錄窗口,引入Microsoft.Windows.Shell。可參考 WPF Custom Chrome Library 和  MSDN WindowChrome Class 有相關自定義窗口實現。前端框架

最小化、最大化、關閉按鈕功能實現可參考上面的例子。微信

登錄按鈕,自定義Style,重寫Button的Template,參考代碼以下:app

 <Style x:Key="LogginButton" TargetType="{x:Type Button}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid  >
                        <Border   x:Name="Bd" Background="{TemplateBinding Background }" BorderBrush="#d3d3d3" BorderThickness="1">
                        </Border>
                        <ContentPresenter  x:Name="contentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="Bd" Property="BorderBrush" Value="#08bd14"/>
                            <Setter TargetName="Bd" Property="Opacity" Value="0.8"/>
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="Bd" Property="Background" Value="#f3f3f3"/>
                            <Setter TargetName="contentPresenter" Property="Margin" Value="2,2,0,0"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
View Code

記住密碼,採用 XmlSerializer 把用戶信息序列化到本地xml配置文件中,程序啓動時加載該xml配置文件。用法 MSDN XmlSerialize
框架

 

2、聊天窗口,信息發送

功能:文字發送,表情發送,圖片發送,屏幕截圖,快捷回覆

 

RichTextBox 相關實現:文字,表情,圖片全部輸入都是在富文本框 裏實現,所以針對 TextChanged 事件對輸入進行一系列處理。

文字:不用作任何處理。

表情:文本框裏輸入的是表情的轉義符號,而後根據轉義符號找到對應表情圖片進行替換。InlineUIContainer

Gif 動態圖:WPF中不支持Gif,因此要編寫自定義用戶控件做爲用來顯示gif表情。參考 周銀輝 [WPF疑難]在WPF中顯示動態GIF

截圖功能:源碼在網上找到的,是Winform的一個截圖。作了小許修改引進到項目。

 參考:C# 實現完整功能的截圖控件(4)-完整版 http://www.csharpwin.com/csharpresource/2588.shtml#PageTop

 

3、客戶列表

控件爲 TabControl,重寫了TabControl 的Style 和 TabItem的Style

    <Style x:Key="CustomerTabStyle" TargetType="{x:Type TabControl}">
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="Padding" Value="4,4,4,4"/>
        <Setter Property="Background" Value="#F9F9F9"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabControl}">
                    <Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition x:Name="ColumnDefinition0"/>
                            <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
                            <RowDefinition x:Name="RowDefinition1" Height="*"/>
                        </Grid.RowDefinitions>
                        <TabPanel x:Name="HeaderPanel" Grid.Column="0" Background="#f6f6f6" IsItemsHost="true"  Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
                        <Border x:Name="ContentPanel"  Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
                            <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="ConnectedTabItemStyle" TargetType="{x:Type TabItem}">
        <Setter Property="Foreground" Value="Black"/>
        <Setter Property="Padding" Value="20,8,20,0"/>
        <Setter Property="BorderBrush" Value="Transparent"/>
        <Setter Property="Background" Value="#b9c0cc"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Grid SnapsToDevicePixels="true">
                        <Border x:Name="Bd" Background="#f6f6f6" Padding="{TemplateBinding Padding}">
                            <StackPanel>
                                <Path  Width="18" Height="18"  Stretch="Fill" Fill="{TemplateBinding Background}" Data="F1 M 38,19C 43.5417,19 45.9167,22.1667 45.1174,28.8134C 45.8315,29.2229 46.3125,29.9928 46.3125,30.875C 46.3125,31.9545 45.5923,32.8658 44.6061,33.1546C 44.1941,34.623 43.5543,35.9229 42.75,36.9628L 42.75,41.9583C 45.3889,42.4861 47.5,42.75 50.6667,44.3333C 53.8333,45.9167 54.8889,47.3681 57,49.4792L 57,57L 19,57L 19,49.4792C 21.1111,47.3681 22.1667,45.9167 25.3333,44.3333C 28.5,42.75 30.6111,42.4861 33.25,41.9583L 33.25,36.9628C 32.4457,35.9229 31.8059,34.623 31.3939,33.1546C 30.4077,32.8658 29.6875,31.9545 29.6875,30.875C 29.6875,29.9928 30.1685,29.2229 30.8826,28.8134C 30.0833,22.1667 32.4583,19 38,19 Z "/>
                                <Border HorizontalAlignment="Center" x:Name="BottomBd" Margin="-6,-6,0,0" Visibility="Hidden">
                                    <Path  Fill="#e1e1e1" Data="M7.41,15.41L12,10.83L16.59,15.41L18,14L12,8L6,14L7.41,15.41Z" />
                                </Border>
                            </StackPanel>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter Property="Background" TargetName="Bd" Value="#ededef"/>
                        </Trigger>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter Property="Panel.ZIndex" Value="1"/>
                            <Setter Property="Background" TargetName="Bd" Value="#ffffff"/>
                            <Setter Property="Background" Value="#08bd14"/>
                            <Setter Property="Visibility" TargetName="BottomBd" Value="Visible"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="false"/>
                                <Condition Property="IsMouseOver" Value="true"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="BorderBrush" TargetName="Bd" Value="#ffffff"/>
                        </MultiTrigger>

                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
View Code

 

4、快捷回覆面板

應用 TreeView 加 HierarchicalDataTemplate 實現樹形列表。

 

5、轉接客戶

自定義轉接客戶窗口,樣式Xaml代碼以下:

<Style x:Key="NoResize_Window" TargetType="{x:Type Window}">
                        <Setter Property="FontFamily" Value="Consolas,Microsoft YaHei" />
                        <Setter Property="ResizeMode" Value="CanMinimize" />
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type Window}">
                                    <Grid>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="30" />
                                            <RowDefinition Height="*" />
                                        </Grid.RowDefinitions>
                                        <Border Grid.Row="0"  >
                                            <Border.Background>
                                                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                                    <GradientStop Color="#494A52" Offset="0"/>
                                                    <GradientStop Color="#45464f" Offset="1"/>
                                                </LinearGradientBrush>
                                            </Border.Background>
                                            <Grid>
                                                <!--Icon and Title-->
                                                <DockPanel     >
                                                    <TextBlock Margin="12,0,0,0" Text="{TemplateBinding Title}" FontFamily="Calibri"  VerticalAlignment="Center" Foreground="#FFFFFF" />
                                                    <StackPanel HorizontalAlignment="Right" Orientation="Horizontal" VerticalAlignment="Top">
                                                        <ctrl:MinAndCloseCaptionButton></ctrl:MinAndCloseCaptionButton>
                                                    </StackPanel>
                                                </DockPanel>
                                            </Grid>
                                        </Border>

                                        <Grid Grid.Row="1" >
                                            <Border Background="{TemplateBinding Background}"
                                        BorderBrush="{TemplateBinding BorderBrush}"  
                                        BorderThickness="{TemplateBinding BorderThickness}"
                                        Padding="{TemplateBinding Margin}"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"  >
                                                <ContentPresenter />
                                            </Border>
                                        </Grid>
                                    </Grid>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
View Code

轉接客戶列表,樣式Xaml代碼以下:

    <Style x:Key="OnlineUserListBoxStyle" TargetType="{x:Type ListBox}">
        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
        <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
        <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBox}">
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
                        <DockPanel>
                            <Border BorderBrush="#dbdbdb" BorderThickness="0,0,0,1" DockPanel.Dock="Top">
                                <Grid Background="#f6f6f6"  TextElement.Foreground="#999999" DockPanel.Dock="Top">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Margin="5,7,0,6" Grid.Column="0">狀態</TextBlock>
                                    <TextBlock Margin="5,7,0,6" Grid.Column="1">工號</TextBlock>
                                    <TextBlock Margin="5,7,0,6" Grid.Column="2">暱稱</TextBlock>
                                </Grid>
                            </Border>
                            <ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
                                <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </ScrollViewer>
                        </DockPanel>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="OnlineUserListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="Padding" Value="2,0,0,0"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>

                            <StackPanel Grid.Column="0" Orientation="Horizontal" >
                                <Border Margin="4,2,4,2" Height="24" Width="24" >
                                    <Grid>
                                        <Path Fill="#6f6f6f" Data="M6,17C6,15 10,13.9 12,13.9C14,13.9 18,15 18,17V18H6M15,9A3,3 0 0,1 12,12A3,3 0 0,1 9,9A3,3 0 0,1 12,6A3,3 0 0,1 15,9M3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3H5C3.89,3 3,3.9 3,5Z"  />
                                        <Path Visibility="{Binding Path=IsOnLine,Converter={StaticResource BoolToVisibilityConverter}}" Fill="#8bc34a" Data="M6,17C6,15 10,13.9 12,13.9C14,13.9 18,15 18,17V18H6M15,9A3,3 0 0,1 12,12A3,3 0 0,1 9,9A3,3 0 0,1 12,6A3,3 0 0,1 15,9M3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3H5C3.89,3 3,3.9 3,5Z" />
                                    </Grid>
                                </Border>
                                <TextBlock Padding="4,0,4,0" VerticalAlignment="Center"  Text="{Binding Path=OnLineStatus}" />
                            </StackPanel>
                            <StackPanel Grid.Column="1" Orientation="Horizontal"  >
                                <TextBlock Padding="4,0,4,0"  VerticalAlignment="Center" Text="{Binding Path=Name}"/>
                            </StackPanel>
                            <StackPanel Grid.Column="2" Orientation="Horizontal"  >
                                <TextBlock Padding="4,0,4,0"  VerticalAlignment="Center" Text="{Binding Path=RealName}"/>
                            </StackPanel>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter Property="Background" TargetName="Bd" Value="#9ea5b8"/>
                            <Setter Property="Foreground" Value="#ffffff"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="false" />
                                <Condition Property="IsMouseOver" Value="true" />
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="#e0e1e5"/>
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
View Code

 

關於以上控件的事件與命令,引進System.Windows.Interactivity.

在Xmal中導入命名控件 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

使用代碼以下:

                <ListBox Margin="12,0,12,0" BorderThickness="1" 
                                 Style="{DynamicResource OnlineUserListBoxStyle}" 
                                 ItemContainerStyle="{DynamicResource OnlineUserListBoxItemStyle}"
                                 ItemsSource="{Binding Path= AllUsers}"
                                 SelectedItem="{Binding Path=SelectedUser}"
                                 >
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="SelectionChanged">
                            <i:InvokeCommandAction Command="{Binding Path= UserSelectedChangedCommand}" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </ListBox>
View Code

 

系統運行截圖:

 

說明:

程序UI佈局及展現爲模仿微信多客服官方程序,全部樣式源碼爲本人所寫及參考網上部分資源。

程序中所用圖標來源於這兩個資源庫:http://modernuiicons.com/  https://materialdesignicons.com/

 

小結:

本文只做了簡單的介紹,主要介紹UI上的一些實現和功能介紹。具體後臺業務邏輯看之後可否補上,包括Prism使用,和微信公衆號相關的知識。

 

博客地址:http://www.cnblogs.com/zhoujunding博客版權:本文以學習、研究和分享爲主,歡迎轉載,但必須在文章頁面明顯位置標明原文鏈接並保留此處說明。若是文中有不妥或者錯誤的地方還望您指出,以避免讓讀者產生誤解。感謝您的閱讀,喜歡就點個贊,【推薦】一下!

相關文章
相關標籤/搜索