-
C# 值得永久收藏的WPF项目实战(经典)
但是可能这些都是把一个综合性的项目分多个部分分别讲述的,有些初学者没有从前往后连续起来阅读的话,后面的部分可能就不容易理解了。其次,因为没有整体的构思,随着内容的增加,项目越来越显得笨重和凌乱,所以今天我重新搞了一个项目,希望以尽量少的代码,涵盖尽量多的知识点,帮助大家更好的理解和使用CM框架。
02
—
重要知识点
-
CM框架的配置和启动;
-
CM框架自带ioc容器SimpleContainer用法;
-
MVVM开发模式;
-
事件聚合器EventAggregator进行事件发布和订阅;
-
属性通知:
① CM框架下基类PropertyChangedBase用法;
②PropertyChanged.Fody.3.1.3下 [AddINotifyPropertyChangedInterface]用法;
-
日志框架:Common.Logging和log4net用法;
-
CM框架下命名约定以及事件关联;
-
用第三方库Xceed.Wpf.Toolkit.dll做等待窗体;
-
CM框架下Conductor用法;
-
CM框架下IWindowManager;
-
双检锁单例模式用法;
-
ListBox数据绑定以及窗体切换;
如果以上知识点你都不敢兴趣或者已经熟知,那这篇文章不适合你,看到这里你就可以关闭网页了!
03
—
运行结果
04
—
项目说明
项目主要包括的类文件如下图:
① MainWindowViewModel.cs类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
using PropertyChanged; using System.Collections.ObjectModel; namespace Caliburn.Micro.Hello { [AddINotifyPropertyChangedInterface] public class MainWindowViewModel : PropertyChangedBase, IViewModel { private static readonly Common.Logging.ILog logger = Common.Logging.LogManager.GetLogger<MainWindowViewModel>(); public IViewModel ActiveWindowView { get ; set ; } public ObservableCollection< string > ListBoxItems { get ; set ; } public string SelectedItem { get ; set ; } public MainWindowViewModel() { logger.Info($ "Enter [MainWindowViewModel]." ); ListBoxItems = new ObservableCollection< string >() { }; ListBoxItems.Add( "ShellView" ); ListBoxItems.Add( "EventAggregatorView" ); ListBoxItems.Add( "ConductorView" ); logger.Info($ "Leave [MainWindowViewModel]." ); } public void ListBoxItems_SelectionChanged() { switch (SelectedItem) { case "ShellView" : ActiveWindowView = new ShellViewModel(); break ; case "EventAggregatorView" : ActiveWindowView = EventAggregatorViewModel.Instance; break ; case "ConductorView" : ActiveWindowView = new ConductorViewModel(); break ; default : break ; } } } } |
-
[
-
logger是定义的common logging的一个通用日志,需要在nuget上引用:Common.Logging.Log4Net1213;
-
ListBoxItems_SelectionChanged()是listbox的选择改变事件:
需要在前台附加事件:
-
12
<ListBox Name=
"ListBoxItems"
Grid.Column=
"0"
SelectedItem=
"{Binding SelectedItem}"
Margin=
"2"
cal:Message.Attach=
"[Event SelectionChanged] = [Action ListBoxItems_SelectionChanged]"
/>
ActiveWindowView 是我的主窗体,选择那个就激活那个
-
1
<ContentControl Name=
"ActiveWindowView"
/>
②ShellViewModel.cs类:
从ioc容器获取一个IWindowManager并显示:
-
123
SimpleContainerViewModel simpleContainerViewModel =
new
SimpleContainerViewModel();
IWindowManager windowManager = IoC.Get<IWindowManager>();
windowManager.ShowDialog(simpleContainerViewModel);
CanSayHello和SayHello,只有CanSayHello条件满足才会执行SayHello
-
12345678
public
bool
CanSayHello
{
get
{
return
!
string
.IsNullOrWhiteSpace(Name); }
}
public
void
SayHello()
{
}
③EventAggregatorViewModel.cs
双检锁线程安全的单例模式:
-
12345678910111213141516171819202122
private
static
EventAggregatorViewModel instance;
private
static
object
locker =
new
object
();
/// <summary>
/// 双检锁
/// </summary>
public
static
EventAggregatorViewModel Instance
{
get
{
if
(instance ==
null
)
{
lock
(locker)
{
if
(instance ==
null
)
{
instance =
new
EventAggregatorViewModel();
}
}
}
return
instance;
}
}
事件订阅:需要继承事件接口IHandle<PersonInfoEven>
-
123
private
readonly
IEventAggregator eventAggregator;
this
.eventAggregator = IoC.Get<IEventAggregator>();
this
.eventAggregator.Subscribe(
this
);
事件处理方法:
-
1234
public
void
Handle(PersonInfoEven message)
{
PersonInfo = message.ToString();
}
④SimpleContainerViewModel.cs
方法1 同步ui发布事件
-
1
this
.eventAggregator.PublishOnUIThread(
"i am a chinese"
);
方法2 开线程去发布
-
123456789
this
.eventAggregator.Publish(
new
PersonInfoEven() {
Name =
"ZYR"
, Age = 18, Sex =
"man"
},
action =>
{
//方式①
//Task.Factory.StartNew(action);
//方式②
Task.Run(action);
});
等待窗体BusyIndicator ,需要引用第三方库Xceed.Wpf.Toolkit,
并添加名称空间:
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
-
1
<xctk:BusyIndicator Name=
"busyIndicator"
BusyContent=
"Publish Event ..."
IsBusy=
"{Binding IsShow}"
Style=
"{x:Null}"
>
⑤ConductorViewModel.cs:此类需要继承Conductor<object>
将需要激活的实例放到ActivateItem,就可以从界面绑定激活对应实例窗体
ActivateItem(new ShellViewModel());
05
—