最近在学习 Prsim 和WPF,在油管上找到了一个 PrsimOutlook 项目,作者是 Brian Lagunas ,是当年 Prsim 搬家到GitHub时交给社区的三位贡献者之一.
照着视频学习加上有源代码,视频作者就是Prsim的作者之一,对Prsim相当的了解,视频思路清晰,代码水平高,值得初学习.
以往文章链接
C# WPF Prsim PrsimOutlook学习记录(一)
C# WPF Prsim PrsimOutlook学习记录(二)
C# WPF Prsim PrsimOutlook学习记录(三)
相关链接
- PrsimOutlook 油管视频链接
- Prsim官网文档
- Prsim官方提供的一些例程代码
- PrsimOutlook 油管视频配套代码 Github
- PrsimOutlook视频中用到的UI框架,可以在Nuget中使用试用版
- Brian Lagunas的个人博客,里面有很多文章
视频四 Creating a Service 学习记录
注:学习记录只是思路的整理,并没有把所有源码都贴在这里,具体源码可以看上方的链接下载
这节视频比较简单,主要是搭建了一个服务和填充了些数据
上一节已经将ContentRegion和RibbonRegion之前的导航和共享 DataContext完成了
首先现在 Business 项目中创建一个BusinessBase,继承 BindableBase
namespace PrismOutlook.Business
{
public class BusinessBase :BindableBase
{
}
}
再创建一个MailMessage类,这个类里面有 邮件的属性,比如发送人,CC,To,Body,发送时间等属性,由于这些属性是需要Binding的,所以继承 BusinessBase
namespace PrismOutlook.Business
{
public class MailMessage :BusinessBase
{
public int Id {
get; set; }
private string _from;
public string From
{
get {
return _from; }
set {
SetProperty(ref _from, value); }
}
private string _subject;
public string Subject
{
get {
return _subject; }
set {
SetProperty(ref _subject, value); }
}
private ObservableCollection<string> _to;
public ObservableCollection<string> To
{
get {
return _to; }
set {
SetProperty(ref _to, value); }
}
private ObservableCollection<string> _cc;
public ObservableCollection<string> CC
{
get {
return _cc; }
set {
SetProperty(ref _cc, value); }
}
private string _body;
public string Body
{
get {
return _body; }
set {
SetProperty(ref _body, value); }
}
private DateTime _dateSent;
public DateTime DateSent
{
get {
return _dateSent; }
set {
SetProperty(ref _dateSent, value); }
}
}
}
有了Model,现在需要一个服务,来提供数据
下面开始些Services的接口
Mail Module只需要调用 服务的接口,对具体的执行内容不需要关心
namespace PrsimOutlook.Services.Interfaces
{
public interface IMailServices
{
IList<MailMessage> GetInboxItems();
IList<MailMessage> GetSentItems();
IList<MailMessage> GetDeletedItems();
}
}
Service的具体数据的执行和Service的接口也不要放在一个项目里,这样写单元测试或者想更换的时候,随时更换
下面写 Service的实现
目前只填充了收件箱的数据
namespace PrsimOutlook.Services
{
public class MailService : IMailServices
{
static List<MailMessage> InboxItems = new List<MailMessage>()
{
new MailMessage()
{
Id = 1,
From = "jerrynixon@microsoft.com",
To = new ObservableCollection<string>(){
"jane@doe.com", "john@doe.com" },
Subject = "This is a test email",
Body = "this is the body of an email",
DateSent = DateTime.Now
},
new MailMessage()
{
Id = 2,
From = "jerrynixon@microsoft.com",
To = new ObservableCollection<string>(){
"jane@doe.com", "john@doe.com" },
Subject = "This is a test email 2",
Body = "this is the body of an email 2",
DateSent = DateTime.Now.AddDays(-1)
},
new MailMessage()
{
Id = 3,
From = "jerrynixon@microsoft.com",
To = new ObservableCollection<string>(){
"jane@doe.com", "john@doe.com" },
Subject = "This is a test email 3",
Body = "this is the body of an email 3",
DateSent = DateTime.Now.AddDays(-5)
},
};
static List<MailMessage> SentItems = new List<MailMessage>() {
};
static List<MailMessage> DeletedItems = new List<MailMessage>() {
};
public IList<MailMessage> GetInboxItems()
{
return InboxItems;
}
public IList<MailMessage> GetSentItems()
{
return SentItems;
}
public IList<MailMessage> GetDeletedItems()
{
return DeletedItems;
}
}
}
之后我们要注入到MailModule中,因为我们不想让其他的Module知道 MailService的存在
在MailModule中
public void RegisterTypes(IContainerRegistry containerRegistry)
{
ViewModelLocationProvider.Register<MailGroup, MainGroupViewModel>();
containerRegistry.RegisterForNavigation<MailList, MailListViewModel>();
//注册
containerRegistry.RegisterSingleton<IMailServices, MailService>();
}
在MailListViewModel改写一下,获取服务的实例
namespace PrsimOutlook.Modules.Mail.ViewModels
{
public class MailListViewModel : ViewModelBase
{
private readonly IMailServices _mailServices;
private ObservableCollection<MailMessage> _messages;
public ObservableCollection<MailMessage> Messages
{
get {
return _messages; }
set {
SetProperty(ref _messages, value); }
}
private MailMessage _selectedMessage;
public MailMessage SelectedMessage
{
get {
return _selectedMessage; }
set {
SetProperty(ref _selectedMessage, value); }
}
public MailListViewModel(IMailServices mailServices)
{
this._mailServices = mailServices;
}
public override void OnNavigatedTo(NavigationContext navigationContext)
{
//Title = navigationContext.Parameters.GetValue<string>("id");
var floder = navigationContext.Parameters.GetValue<string>(FolderParameters.FolderKey);
switch (floder)
{
case FolderParameters.Inbox:
Messages = new ObservableCollection<MailMessage>(_mailServices.GetInboxItems());
break;
case FolderParameters.Sent:
Messages = new ObservableCollection<MailMessage>(_mailServices.GetSentItems());
break;
case FolderParameters.Deleted:
Messages = new ObservableCollection<MailMessage>(_mailServices.GetDeletedItems());
break;
default:
break;
}
}
}
}
创建一下 FolderParameters类
public class FolderParameters
{
public const string FolderKey = "Folder";
public const string Inbox = "Inbox";
public const string Sent = "Sent";
public const string Deleted = "Deleted";
}
重构一下 GenerateMenu方法
void GenerateMenu()
{
Items = new ObservableCollection<NavigationItem>();
/*var root = new NavigationItem() { Caption = "Personal Folder", NavigationPath = "MailList?id=Default" };
root.Items.Add(new NavigationItem() { Caption = "Inbox", NavigationPath = "MailList?id=Inbox" });
root.Items.Add(new NavigationItem() { Caption = "Deleted", NavigationPath = "MailList?id=Deleted" });
root.Items.Add(new NavigationItem() { Caption = "Sent", NavigationPath = "MailList?id=Sent" });*/
var root = new NavigationItem() {
Caption = "Personal Folder", NavigationPath = "MailList?id=Default",IsExpended = true };
root.Items.Add(new NavigationItem() {
Caption = Resource.Folder_Inbox, NavigationPath = GetNavigationPath(FolderParameters.Inbox) });
root.Items.Add(new NavigationItem() {
Caption = Resource.Folder_Deleted, NavigationPath = GetNavigationPath(FolderParameters.Deleted) });
root.Items.Add(new NavigationItem() {
Caption = Resource.Folder_Sent, NavigationPath = GetNavigationPath(FolderParameters.Sent) });
Items.Add(root);
}
string GetNavigationPath(string folder)
{
return $"MailList?{
FolderParameters.FolderKey}={
folder}";
}
这里做了个本地化的操作
重新修改一下MailList.xaml
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="370"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Background="White" Margin="5,0,0,0" >
<ig:XamDataGrid DataSource="{Binding Messages}" ActiveDataItem="{Binding SelectedMessage}">
<ig:XamDataGrid.FieldSettings>
<ig:FieldSettings AllowEdit="False"/>
</ig:XamDataGrid.FieldSettings>
<ig:XamDataGrid.FieldLayoutSettings>
<ig:FieldLayoutSettings AutoGenerateFields="False"></ig:FieldLayoutSettings>
</ig:XamDataGrid.FieldLayoutSettings>
<ig:XamDataGrid.FieldLayouts>
<ig:FieldLayout>
<ig:TextField Name="From"></ig:TextField>
<ig:TextField Name="Subject"></ig:TextField>
<ig:DateTimeField Name="DateSent"></ig:DateTimeField>
</ig:FieldLayout>
</ig:XamDataGrid.FieldLayouts>
</ig:XamDataGrid>
</Grid>
<!--Mail Preview Area-->
<Border Grid.Column="1" Margin="5,0,0,0" Background="White">
<StackPanel>
<TextBlock Margin="5" Text="{Binding SelectedMessage.From}"/>
<TextBlock Margin="5" Text="{Binding SelectedMessage.To}"/>
<TextBlock Margin="5" Text="{Binding SelectedMessage.CC}"/>
<TextBlock Margin="5" Text="{Binding SelectedMessage.Subject}"/>
<TextBlock Margin="5" Text="{Binding SelectedMessage.From}"/>
<TextBlock Margin="5" Text="{Binding SelectedMessage.Body}"/>
</StackPanel>
</Border>
<GridSplitter Grid.Column="1" VerticalAlignment="Stretch" Width="10" HorizontalAlignment="Left" Grid.RowSpan="100">
<GridSplitter.Template>
<ControlTemplate>
<Grid Background="White">
<Rectangle Width="1" Fill="#D4D4D4" Margin="0,5,0,0" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</GridSplitter.Template>
</GridSplitter>
</Grid>
这样程序启动,就可以完成程序开始程序的功能了
还有一个程序一打开默认显示在Inbox上
在MailGroup中 写一下这个
public MailGroup()
{
InitializeComponent();
_dataTree.Loaded += DataTree_Loaded;
}
private void DataTree_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
_dataTree.Loaded -= DataTree_Loaded;
var parentNode = _dataTree.Nodes[0];
var nodeToSelect = parentNode.Nodes[0];
nodeToSelect.IsSelected = true;
}
总结
这节主要是搭建了服务,填充了数据.修改了一下MailList.xaml的界面显示.还有重构了一下导航的参数部分.