├── .gitattributes
├── .github
└── workflows
│ └── PublishNuget.yml
├── .gitignore
├── README.md
├── Unicorn.sln
├── examples
└── ViewManagerDemo
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── AssemblyInfo.cs
│ ├── CommandListWindow.xaml
│ ├── CommandListWindow.xaml.cs
│ ├── Components
│ ├── PopupViewHeader.xaml
│ └── PopupViewHeader.xaml.cs
│ ├── Dialogs
│ ├── DialogWithEvent.xaml
│ ├── DialogWithEvent.xaml.cs
│ ├── FullScreenDialog.xaml
│ ├── FullScreenDialog.xaml.cs
│ ├── NormalDialog.xaml
│ └── NormalDialog.xaml.cs
│ ├── Flyouts
│ ├── FlyoutLocationDemo.xaml
│ └── FlyoutLocationDemo.xaml.cs
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ ├── Resources
│ └── Images
│ │ ├── Background.jpg
│ │ └── Logo.ico
│ ├── StandardWindow.xaml
│ ├── StandardWindow.xaml.cs
│ ├── ViewManagerDemo.csproj
│ └── Views
│ ├── DialogsDemoView.xaml
│ ├── DialogsDemoView.xaml.cs
│ ├── FlyoutsDemoView.xaml
│ ├── FlyoutsDemoView.xaml.cs
│ ├── ReadMe.xaml
│ └── ReadMe.xaml.cs
└── src
└── Unicorn.ViewManager
├── AssemblyInfo.cs
├── DefaultPopupItemContainer.cs
├── Dialog.cs
├── DialogContainer.cs
├── Flyout.cs
├── FlyoutContainer.cs
├── IPopupItemContainer.cs
├── ModalResult.cs
├── PopupItem.cs
├── PopupItemContainer.cs
├── PopupStack.cs
├── PopupStackControl.cs
├── Preferences
└── ViewPreferences.cs
├── Resource
└── Images
│ ├── box_error.png
│ ├── box_info.png
│ ├── box_question.png
│ └── box_warning.png
├── RichViewControl.cs
├── RichViewItem.cs
├── RichViewWindow.cs
├── System
└── Windows
│ ├── MessageDialogBox.cs
│ └── ProcessDialogBox.cs
├── Themes
├── DefaultPopupItemContainer.xaml
├── Dialog.xaml
├── DialogContainer.xaml
├── Flyout.xaml
├── FlyoutContainer.xaml
├── Generic.xaml
├── MessageDialogBox.xaml
├── PopupItemContainer.xaml
├── PopupStack.xaml
├── PopupStackControl.xaml
├── ProcessDialogBox.xaml
├── RichViewControl.xaml
├── RichViewItem.xaml
└── RichViewWindow.xaml
├── Unicorn.ViewManager.csproj
├── ViewCommands.cs
├── ViewManager.cs
└── ViewStackChangedEventArgs.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/workflows/PublishNuget.yml:
--------------------------------------------------------------------------------
1 | name: Publish Nuget
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | publish:
10 | name: Publish to Nuget
11 | runs-on: windows-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v1
15 | - name: Setup .NET Core
16 | uses: actions/setup-dotnet@v1
17 | with:
18 | dotnet-version: 3.1
19 | project_dir: src/Unicorn.ViewManager # Defaults to repository root
20 |
21 | - name: Build with dotnet
22 | run: dotnet pack -c Release src/Unicorn.ViewManager/Unicorn.ViewManager.csproj -o .
23 |
24 | - name: Push Package to Nuget
25 | run: dotnet nuget push *.nupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_API_KEY }} --skip-duplicate
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
Unicorn.ViewManager
3 |
4 | A powerful WPF view management library
5 |
6 |
7 | Supporting .NET Core (3.1)
8 |
9 |
10 |
11 |
12 | ## Installation
13 | - [Nuget](https://www.nuget.org/packages/Unicorn.ViewManager/)
14 |
15 | ```
16 | PM> Install-Package Unicorn.ViewManager
17 | ```
18 |
19 | ## Let's get started
20 | To start, first add this code at MainWindow's constructor.This step is to initialize a main view stack. ViewManager.Instance.MainRichView.SwitchView(object) method is used to switch the main view in the program,it does not belong to the view stack.
21 | ```csharp
22 | public MainWindow()
23 | {
24 | InitializeComponent();
25 |
26 | ViewManager.Instance.InitializeRichView(this);
27 | ViewManager.Instance.ViewPreferences.UsePopupViewAnimations = true;
28 | ViewManager.Instance.MainRichView.SwitchView(new MainView());
29 | }
30 | ```
31 | The second step is to initialize a Unicorn.ViewManager.Dialog or Unicorn.ViewManager.Flyout,you can inherit it in xaml,when you have a Unicorn.ViewManager.Dialog or Unicorn.ViewManager.Flyout,.
32 | you can display it with ViewManager.Instance.Show(PopupItem item) method.
33 | ```csharp
34 | ViewManager.Instance.Show(new FullScreenDialog());//FullScreenDialog is my Dialog instance inherit Dialog
35 | //OR
36 | new FullScreenDialog().Show();//at default main view stack
37 | //OR
38 | new FullScreenDialog().Show(IPopupItemContainer );//IPopupItemContainer is a interface
39 | //OR
40 | new FullScreenDialog().ShowAsModal();//at default main view stack
41 | //OR
42 | new FullScreenDialog().ShowAsModal(IPopupItemContainer );//at custom IPopupItemContainer
43 | ```
44 | you can close it like that.
45 | ```csharp
46 | ViewManager.Instance.Close(Dialog dialog);//FullScreenDialog is my Dialog instance inherit Dialog
47 | //OR
48 | dialog.Close();
49 | ```
50 |
51 | ## View's events
52 | Each view item has four events, they are 'Showing','Shown','Closing','Closed'.
53 | 'Showing','Closing' can be canceled. you can use it like that:
54 | ```csharp
55 | public partial class DialogWithEvent : Dialog
56 | {
57 | public DialogWithEvent()
58 | {
59 | InitializeComponent();
60 | this.Showing += DialogWithEvent_Showing;
61 | this.Shown += DialogWithEvent_Shown;
62 | this.Closing += DialogWithEvent_Closing;
63 | this.Closed += DialogWithEvent_Closed;
64 | }
65 |
66 | private void DialogWithEvent_Closed(object sender, EventArgs e)
67 | {
68 | MessageDialogBox.Show("该Dialog已彻底关闭,并已从视图栈移除,可在此事件处理中处理一些释放问题", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
69 | }
70 |
71 | private void DialogWithEvent_Closing(object sender, System.ComponentModel.CancelEventArgs e)
72 | {
73 | var msresult = MessageDialogBox.Show("Dialog With Event 准备关闭,此时可以取消,是否继续关闭", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question);
74 | if (msresult == MessageBoxResult.No)
75 | {
76 | e.Cancel = true;
77 | }
78 | }
79 |
80 | private void DialogWithEvent_Shown(object sender, EventArgs e)
81 | {
82 | MessageDialogBox.Show("该Dialog已显示完成,可在此事件处理中处理一些加载问题", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
83 | }
84 |
85 | private void DialogWithEvent_Showing(object sender, System.ComponentModel.CancelEventArgs e)
86 | {
87 | var msresult = MessageDialogBox.Show("Dialog With Event 准备显示,此时可以取消,是否继续显示", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question);
88 | if (msresult == MessageBoxResult.No)
89 | {
90 | e.Cancel = true;
91 | }
92 | }
93 | }
94 | ```
95 | See more details in the demo.
96 |
97 |
98 | ## Screenshots
99 | 
100 | 
101 | 
102 | 
103 | 
104 | 
105 | 
106 |
--------------------------------------------------------------------------------
/Unicorn.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29613.14
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unicorn.ViewManager", "src\Unicorn.ViewManager\Unicorn.ViewManager.csproj", "{29000AB0-6056-4BA8-BB86-83F887AE7E3E}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewManagerDemo", "examples\ViewManagerDemo\ViewManagerDemo.csproj", "{15F5DB45-0C77-4561-865A-C10DECC9434D}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x86 = Debug|x86
14 | Release|Any CPU = Release|Any CPU
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {29000AB0-6056-4BA8-BB86-83F887AE7E3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {29000AB0-6056-4BA8-BB86-83F887AE7E3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {29000AB0-6056-4BA8-BB86-83F887AE7E3E}.Debug|x86.ActiveCfg = Debug|x86
21 | {29000AB0-6056-4BA8-BB86-83F887AE7E3E}.Debug|x86.Build.0 = Debug|x86
22 | {29000AB0-6056-4BA8-BB86-83F887AE7E3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {29000AB0-6056-4BA8-BB86-83F887AE7E3E}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {29000AB0-6056-4BA8-BB86-83F887AE7E3E}.Release|x86.ActiveCfg = Release|x86
25 | {29000AB0-6056-4BA8-BB86-83F887AE7E3E}.Release|x86.Build.0 = Release|x86
26 | {15F5DB45-0C77-4561-865A-C10DECC9434D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {15F5DB45-0C77-4561-865A-C10DECC9434D}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {15F5DB45-0C77-4561-865A-C10DECC9434D}.Debug|x86.ActiveCfg = Debug|Any CPU
29 | {15F5DB45-0C77-4561-865A-C10DECC9434D}.Debug|x86.Build.0 = Debug|Any CPU
30 | {15F5DB45-0C77-4561-865A-C10DECC9434D}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {15F5DB45-0C77-4561-865A-C10DECC9434D}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {15F5DB45-0C77-4561-865A-C10DECC9434D}.Release|x86.ActiveCfg = Release|Any CPU
33 | {15F5DB45-0C77-4561-865A-C10DECC9434D}.Release|x86.Build.0 = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | GlobalSection(ExtensibilityGlobals) = postSolution
39 | SolutionGuid = {3998AB32-5B44-4B13-AF0F-2E7E68B672F6}
40 | EndGlobalSection
41 | EndGlobal
42 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/App.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
14 |
18 |
19 | #FF338ECD
20 | #FF338CC7
21 | #FF226FB7
22 | #07000000
23 |
24 |
25 |
26 |
27 |
28 |
29 |
35 |
36 |
78 |
84 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace ViewManagerDemo
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(
4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5 | //(used if a resource is not found in the page,
6 | // or application resource dictionaries)
7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8 | //(used if a resource is not found in the page,
9 | // app, or any theme specific resource dictionaries)
10 | )]
11 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/CommandListWindow.xaml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/CommandListWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Shapes;
12 |
13 | namespace ViewManagerDemo
14 | {
15 | ///
16 | /// CommandListWindow.xaml 的交互逻辑
17 | ///
18 | public partial class CommandListWindow : Window
19 | {
20 | public CommandListWindow()
21 | {
22 | InitializeComponent();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Components/PopupViewHeader.xaml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Components/PopupViewHeader.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 |
14 | namespace ViewManagerDemo.Components
15 | {
16 | ///
17 | /// PopupViewHeader.xaml 的交互逻辑
18 | ///
19 | public partial class PopupViewHeader : UserControl
20 | {
21 |
22 | public object TitleContent
23 | {
24 | get
25 | {
26 | return (object)GetValue(TitleContentProperty);
27 | }
28 | set
29 | {
30 | SetValue(TitleContentProperty, value);
31 | }
32 | }
33 | public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register("TitleContent", typeof(object), typeof(PopupViewHeader), new PropertyMetadata(null));
34 |
35 | public PopupViewHeader()
36 | {
37 | InitializeComponent();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Dialogs/DialogWithEvent.xaml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
32 |
37 |
38 |
39 |
40 |
41 |
48 |
49 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Dialogs/DialogWithEvent.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 |
14 | namespace ViewManagerDemo.Dialogs
15 | {
16 | ///
17 | /// DialogWithEvent.xaml 的交互逻辑
18 | ///
19 | public partial class DialogWithEvent
20 | {
21 | public DialogWithEvent()
22 | {
23 | InitializeComponent();
24 | this.Showing += DialogWithEvent_Showing;
25 | this.Shown += DialogWithEvent_Shown;
26 | this.Closing += DialogWithEvent_Closing;
27 | this.Closed += DialogWithEvent_Closed;
28 | }
29 |
30 | private void DialogWithEvent_Closed(object sender, EventArgs e)
31 | {
32 | MessageDialogBox.Show("该Dialog已彻底关闭,并已从视图栈移除,可在此事件处理中处理一些释放问题", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
33 | }
34 |
35 | private void DialogWithEvent_Closing(object sender, System.ComponentModel.CancelEventArgs e)
36 | {
37 | var msresult = MessageDialogBox.Show("Dialog With Event 准备关闭,此时可以取消,是否继续关闭", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question);
38 | if (msresult == MessageBoxResult.No)
39 | {
40 | e.Cancel = true;
41 | }
42 | }
43 |
44 | private void DialogWithEvent_Shown(object sender, EventArgs e)
45 | {
46 | MessageDialogBox.Show("该Dialog已显示完成,可在此事件处理中处理一些加载问题", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
47 | }
48 |
49 | private void DialogWithEvent_Showing(object sender, System.ComponentModel.CancelEventArgs e)
50 | {
51 | var msresult = MessageDialogBox.Show("Dialog With Event 准备显示,此时可以取消,是否继续显示", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question);
52 | if (msresult == MessageBoxResult.No)
53 | {
54 | e.Cancel = true;
55 | }
56 | }
57 |
58 | private void StackPanel_Click(object sender, RoutedEventArgs e)
59 | {
60 |
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Dialogs/FullScreenDialog.xaml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
33 |
37 |
38 |
39 |
40 |
47 |
48 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Dialogs/FullScreenDialog.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 |
14 | namespace ViewManagerDemo.Dialogs
15 | {
16 | ///
17 | /// FullScreenDialog.xaml 的交互逻辑
18 | ///
19 | public partial class FullScreenDialog
20 | {
21 | public FullScreenDialog()
22 | {
23 | InitializeComponent();
24 | this.Shown += FullScreenDialog_Shown;
25 | }
26 |
27 | private void FullScreenDialog_Shown(object sender, EventArgs e)
28 | {
29 | var dsds = this.FindParentHost();
30 | }
31 |
32 | private void StackPanel_Click(object sender, RoutedEventArgs e)
33 | {
34 | switch (((Button)e.OriginalSource).Name)
35 | {
36 | case "_showChildDialogBt":
37 | this.Show(new NormalDialog());
38 | break;
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Dialogs/NormalDialog.xaml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
33 |
37 |
38 | 当Dialog以模态方式显示时,在同一个视图栈其上不可再显示其它任何视图,MessageDialogBox、ProcessDialogBox除外。当强行在同一个视图栈
39 |
40 |
41 | 显示
42 |
43 |
44 | 其它时,该模态Dialog会以周围闪烁阴影同时系统蜂鸣提示。点击Dialog周围的灰色区域时,该Dialog也会提示。
45 |
46 |
47 |
48 |
54 |
55 |
56 |
57 |
58 |
65 |
66 |
71 |
72 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Dialogs/NormalDialog.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 | using Unicorn.ViewManager;
14 |
15 | namespace ViewManagerDemo.Dialogs
16 | {
17 | ///
18 | /// NormalDialog.xaml 的交互逻辑
19 | ///
20 | public partial class NormalDialog
21 | {
22 | public Visibility SetModalResultBtVisibility
23 | {
24 | get
25 | {
26 | return (Visibility)GetValue(SetModalResultBtVisibilityProperty);
27 | }
28 | set
29 | {
30 | SetValue(SetModalResultBtVisibilityProperty, value);
31 | }
32 | }
33 | public static readonly DependencyProperty SetModalResultBtVisibilityProperty = DependencyProperty.Register("SetModalResultBtVisibility", typeof(Visibility), typeof(NormalDialog), new PropertyMetadata(Visibility.Collapsed));
34 |
35 |
36 | public NormalDialog()
37 | {
38 | InitializeComponent();
39 | }
40 |
41 | private void StackPanel_Click(object sender, RoutedEventArgs e)
42 | {
43 | switch (((Button)e.OriginalSource).Name)
44 | {
45 | case "_setResultBt":
46 | this.ModalResult = new Unicorn.ViewManager.ModalResult
47 | {
48 | Result = $"你输入了 \" {_text.Text} \""
49 | };
50 | break;
51 | }
52 | }
53 |
54 | private void _showAtSameStack_Click(object sender, RoutedEventArgs e)
55 | {
56 | this.ParentHostContainer.Show(new NormalDialog());
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Flyouts/FlyoutLocationDemo.xaml:
--------------------------------------------------------------------------------
1 |
14 |
20 |
21 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Flyouts/FlyoutLocationDemo.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 |
14 | namespace ViewManagerDemo.Flyouts
15 | {
16 | ///
17 | /// FlyoutLocationDemo.xaml 的交互逻辑
18 | ///
19 | public partial class FlyoutLocationDemo
20 | {
21 | public FlyoutLocationDemo()
22 | {
23 | InitializeComponent();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using System.Windows;
9 | using System.Windows.Controls;
10 | using System.Windows.Data;
11 | using System.Windows.Documents;
12 | using System.Windows.Input;
13 | using System.Windows.Media;
14 | using System.Windows.Media.Imaging;
15 | using System.Windows.Navigation;
16 | using System.Windows.Shapes;
17 | using Unicorn.Utilities.Commands;
18 | using Unicorn.ViewManager;
19 | using ViewManagerDemo.Dialogs;
20 | using ViewManagerDemo.Flyouts;
21 | using ViewManagerDemo.Views;
22 |
23 | namespace ViewManagerDemo
24 | {
25 | ///
26 | /// Interaction logic for MainWindow.xaml
27 | ///
28 | public partial class MainWindow
29 | {
30 | public static MainWindow Instance
31 | {
32 | get;
33 | private set;
34 | }
35 |
36 | static MainWindow()
37 | {
38 | DefaultUICommandManager.Instance.CommandCanExecuteAction = CommandCanExecuteAction;
39 | DefaultUICommandManager.Instance.CommandExecuteAction = CommandExecuteAction;
40 | }
41 |
42 | private CommandListWindow _cmdListWindow = new CommandListWindow();
43 | public MainWindow()
44 | {
45 | Instance = this;
46 |
47 | InitializeComponent();
48 | ViewManager.Instance.InitializeRichView(this);
49 | ViewManager.Instance.ViewPreferences.UsePopupViewAnimations = true;
50 | ViewManager.Instance.MainRichView.SwitchView(ReadMe.Instance);
51 |
52 | this.IsVisibleChanged += (sender, e) =>
53 | {
54 | if (this.IsVisible)
55 | {
56 | this._cmdListWindow.Show();
57 | }
58 | };
59 | this.SizeChanged += (sender, e) =>
60 | {
61 | this.RefreshCmdWindowLocation();
62 | };
63 | this.StateChanged += (sender, e) =>
64 | {
65 | this.RefreshCmdWindowLocation();
66 | };
67 | this.LocationChanged += (sender, e) =>
68 | {
69 | this.RefreshCmdWindowLocation();
70 | };
71 | }
72 |
73 | protected override void OnKeyDown(KeyEventArgs e)
74 | {
75 | base.OnKeyDown(e);
76 | if (e.Key == Key.Escape)
77 | {
78 | ViewManager.Instance.Close();
79 | e.Handled = true;
80 | }
81 |
82 | if (e.KeyboardDevice.Modifiers== ModifierKeys.Control)
83 | {
84 | switch (e.Key)
85 | {
86 | case Key.W:
87 | var topitem = ViewManager.Instance.ActiveContainer.TopItem;
88 | StandardWindow.ShowStandard(topitem);
89 | break;
90 | }
91 | }
92 | }
93 |
94 | public void RefreshCmdWindowLocation()
95 | {
96 | this._cmdListWindow.Owner = this;
97 | this._cmdListWindow.Height = this.ActualHeight;
98 | this._cmdListWindow.Left = this.Left + this.ActualWidth;
99 | this._cmdListWindow.Top = this.Top;
100 | }
101 |
102 | private static bool CommandCanExecuteAction(string cmdkey, UICommandParameter parameter)
103 | {
104 | return true;
105 | }
106 |
107 | private async static void CommandExecuteAction(string cmdkey, UICommandParameter parameter)
108 | {
109 | switch (cmdkey)
110 | {
111 | case "DialogsDemoView":
112 | ViewManager.Instance.MainRichView.Show(DialogsDemoView.Instance);
113 | break;
114 |
115 | case "FlyoutsDemoView":
116 | ViewManager.Instance.MainRichView.SwitchView(FlyoutsDemoView.Instance);
117 | break;
118 |
119 | case "ShowMessageDialogBox":
120 | {
121 | var msresult = MessageDialogBox.Show($"是、否、取消MessageDialogBox,根据需要返回结果,请继续...{Environment.NewLine}[是]:是{Environment.NewLine}[否]:否{Environment.NewLine}[取消]:取消", "提示", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
122 | if (msresult == MessageBoxResult.Yes)
123 | {
124 | MessageDialogBox.Show("你点击了 [是]", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
125 | }
126 | else if (msresult == MessageBoxResult.No)
127 | {
128 | MessageDialogBox.Show("你点击了 [否]", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
129 | }
130 | else if (msresult == MessageBoxResult.Cancel)
131 | {
132 | MessageDialogBox.Show("你点击了 [取消],或者直接关闭了", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
133 | }
134 | else
135 | {
136 | MessageDialogBox.Show("不应该返回此结果", "信息", MessageBoxButton.OK, MessageBoxImage.Error);
137 | }
138 | }
139 | break;
140 |
141 | case "ShowProcessDialogBox":
142 | {
143 | using (ProcessDialogBox box = ProcessDialogBox.Show("测试信息", "标题", false, ProcessBoxButton.Cancel | ProcessBoxButton.PauseContinue | ProcessBoxButton.Stop))
144 | using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
145 | {
146 | bool ispause = false;
147 |
148 | box.CancelAction = () =>
149 | {
150 | cancellationTokenSource.Cancel();
151 | };
152 | box.PauseAction = () =>
153 | {
154 | ispause = true;
155 | };
156 | box.StopAction = () =>
157 | {
158 | cancellationTokenSource.Cancel();
159 | };
160 | box.ContinueAction = () =>
161 | {
162 | ispause = false;
163 | };
164 |
165 | await Task.Factory.StartNew(() =>
166 | {
167 | for (int i = 0; i < 200; i++)
168 | {
169 | SpinWait.SpinUntil(() => !ispause || cancellationTokenSource.IsCancellationRequested);
170 | if (cancellationTokenSource.IsCancellationRequested)
171 | {
172 | break;
173 | }
174 |
175 | box.ProcessValue = (double)i / 200 * 100;
176 |
177 | Thread.Sleep(100);
178 | }
179 |
180 | }, cancellationTokenSource.Token);
181 | }
182 | }
183 | break;
184 |
185 | case "Exit":
186 | MainWindow.Instance.Close();
187 | break;
188 | }
189 | }
190 |
191 | protected override void OnClosing(CancelEventArgs e)
192 | {
193 | base.OnClosing(e);
194 |
195 | var msresult = MessageDialogBox.Show($"是否确认关闭?", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question);
196 | if (msresult == MessageBoxResult.No)
197 | {
198 | e.Cancel = true;
199 | }
200 | }
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Resources/Images/Background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrZhangYuan/Unicorn.ViewManager/312e86538393817302cdaa7b1e22c66aeb2c5be4/examples/ViewManagerDemo/Resources/Images/Background.jpg
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Resources/Images/Logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrZhangYuan/Unicorn.ViewManager/312e86538393817302cdaa7b1e22c66aeb2c5be4/examples/ViewManagerDemo/Resources/Images/Logo.ico
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/StandardWindow.xaml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/StandardWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using System.Windows.Data;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Shapes;
13 | using Unicorn.ViewManager;
14 |
15 | namespace ViewManagerDemo
16 | {
17 | ///
18 | /// StandardWindow.xaml 的交互逻辑
19 | ///
20 | public partial class StandardWindow : RichViewWindow
21 | {
22 | public StandardWindow()
23 | {
24 | InitializeComponent();
25 | this.ViewStackChanged += StandardWindow_ViewStackChanged;
26 | }
27 |
28 | private void StandardWindow_ViewStackChanged(object sender, ViewStackChangedEventArgs e)
29 | {
30 | if (!this.Children.Any())
31 | {
32 | this.Close();
33 | }
34 | }
35 |
36 | public static void ShowStandard(PopupItem topitem)
37 | {
38 | topitem.Closed += StandardView_Closed;
39 | topitem.Close();
40 | }
41 | private static void StandardView_Closed(object sender, EventArgs e)
42 | {
43 | PopupItem popupItem = sender as PopupItem;
44 | popupItem.Closed -= StandardView_Closed;
45 |
46 | StandardWindow window = new StandardWindow();
47 | window.Show();
48 | window.Activate();
49 | window.Show(popupItem);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/ViewManagerDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | netcoreapp3.1
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Views/DialogsDemoView.xaml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
30 |
34 |
35 | Dialog是最通用的视图项,它在程序中作为功能性弹出窗,甚至可作为一个功能模块的主页,该类继承自 Unicorn.ViewManager.PopupItem 该类是视图栈的项基类。
36 |
37 |
38 | 在名称空间System(该名称空间位于Unicorn.ViewManager.dll)下有两个集成的特殊的Dialog:MessageDialogBox、ProcessDialogBox
39 |
40 |
41 |
42 |
43 | MessageDialogBox
44 |
45 |
46 | 和系统内置的MessageBox功能完全一致,但MessageDialogBox可重写样式(Template必须包含指定的PART),详情查看Demo项目的App.xaml文件
47 |
48 |
49 |
50 |
51 | ProcessDialogBox
52 |
53 |
54 | 作为一个进度框给用户实时反馈一些操作的进度,也可重写样式(Template必须包含指定的PART),详情查看Demo项目的App.xaml文件
55 |
56 |
57 |
58 |
59 |
60 |
67 |
68 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Views/DialogsDemoView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 | using Unicorn.ViewManager;
14 | using ViewManagerDemo.Dialogs;
15 |
16 | namespace ViewManagerDemo.Views
17 | {
18 | ///
19 | /// DialogsDemoView.xaml 的交互逻辑
20 | ///
21 | public partial class DialogsDemoView
22 | {
23 |
24 | private static DialogsDemoView _instance = null;
25 | public static DialogsDemoView Instance
26 | {
27 | get
28 | {
29 | if (_instance == null)
30 | {
31 | _instance = new DialogsDemoView();
32 | }
33 | return _instance;
34 | }
35 | }
36 |
37 | public DialogsDemoView()
38 | {
39 | InitializeComponent();
40 | }
41 |
42 | private void StackPanel_Click(object sender, RoutedEventArgs e)
43 | {
44 | switch (((Button)e.OriginalSource).Name)
45 | {
46 | case "_showFullScreen":
47 | this.Show(new FullScreenDialog());
48 | break;
49 |
50 | case "_showNormal":
51 | this.Show(new NormalDialog());
52 | break;
53 | case "_showEventBt":
54 | this.Show(new DialogWithEvent());
55 | break;
56 |
57 | case "_showDialogAsModalBt":
58 | var modalresult = this.ShowModal(new NormalDialog() { SetModalResultBtVisibility = Visibility.Visible });
59 | if (modalresult != null)
60 | {
61 | MessageDialogBox.Show(modalresult.Result + "");
62 | }
63 | break;
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Views/FlyoutsDemoView.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
31 |
32 | Flyout的基本用法显示、关闭、模态、事件等和Dialog几乎完全一样,因为它俩都是继承自 Unicorn.ViewManager.PopupItem 该类是视图栈的项基类
33 |
34 |
35 |
36 |
37 |
38 |
39 |
46 |
47 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Views/FlyoutsDemoView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 | using Unicorn.ViewManager;
14 | using ViewManagerDemo.Flyouts;
15 |
16 | namespace ViewManagerDemo.Views
17 | {
18 | ///
19 | /// FlyoutsDemoView.xaml 的交互逻辑
20 | ///
21 | public partial class FlyoutsDemoView : UserControl
22 | {
23 |
24 | private static FlyoutsDemoView _instance = null;
25 | public static FlyoutsDemoView Instance
26 | {
27 | get
28 | {
29 | if (_instance == null)
30 | {
31 | _instance = new FlyoutsDemoView();
32 | }
33 | return _instance;
34 | }
35 | }
36 |
37 | public FlyoutsDemoView()
38 | {
39 | InitializeComponent();
40 | }
41 |
42 | private void StackPanel_Click(object sender, RoutedEventArgs e)
43 | {
44 | FlyoutLocationDemo flyout = new FlyoutLocationDemo();
45 |
46 | switch (((Button)e.OriginalSource).Name)
47 | {
48 | case "_showFlyoutLeft":
49 | flyout.Width = 250;
50 | flyout.FlyoutLocation = FlyoutLocation.Left;
51 | break;
52 |
53 | case "_showFlyoutTop":
54 | flyout.Height = 250;
55 | flyout.FlyoutLocation = FlyoutLocation.Top;
56 | break;
57 |
58 | case "_showFlyoutRight":
59 | flyout.Width = 250;
60 | flyout.FlyoutLocation = FlyoutLocation.Right;
61 | break;
62 |
63 | case "_showFlyoutBottom":
64 | flyout.Height = 250;
65 | flyout.FlyoutLocation = FlyoutLocation.Bottom;
66 | break;
67 | }
68 |
69 | ViewManager.Instance.Show(flyout);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Views/ReadMe.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
30 |
31 |
32 |
33 | Unicorn.ViewManager
34 |
35 |
36 |
37 | 视图管理库基于视图栈的形式去层叠项目中的视图,通过 ViewManager.Instance.InitializeRichView(ContentControl) 去初始化一个主视图栈,视图项为
38 |
39 |
40 |
41 | Unicorn.ViewManager.PopupItem
42 |
43 |
44 | ,库预设的两个PopupItem类型为
45 |
46 | Unicorn.ViewManager.Dialog
47 |
48 |
49 | 和
50 |
51 | Unicorn.ViewManager.Flyout
52 |
53 |
54 | ,自定义视图可继承自这两个预设视图项,也可以直接继承自Unicorn.ViewManager.PopupItem,
55 | 随后可通过ViewManager.Instance.Show(PopupItem)方法去显示视图
56 |
57 |
58 | 在Unicorn.ViewManager.dll里的名称空间System下有两个集成的特殊的Dialog:
59 |
60 |
61 |
62 | MessageDialogBox
63 |
64 |
65 | 、
66 |
67 | ProcessDialogBox
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/examples/ViewManagerDemo/Views/ReadMe.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using System.Windows.Data;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Navigation;
13 | using System.Windows.Shapes;
14 |
15 | namespace ViewManagerDemo.Views
16 | {
17 | ///
18 | /// ReadMe.xaml 的交互逻辑
19 | ///
20 | public partial class ReadMe : UserControl
21 | {
22 |
23 | private static ReadMe _instance = null;
24 | public static ReadMe Instance
25 | {
26 | get
27 | {
28 | if (_instance == null)
29 | {
30 | _instance = new ReadMe();
31 | }
32 | return _instance;
33 | }
34 | }
35 |
36 | public ReadMe()
37 | {
38 | InitializeComponent();
39 | }
40 |
41 | private void TextBlock_Click(object sender, RoutedEventArgs e)
42 | {
43 | if (e.OriginalSource is Hyperlink hyperlink
44 | && hyperlink.NavigateUri!=null
45 | && !string.IsNullOrEmpty(hyperlink.NavigateUri.AbsoluteUri))
46 | {
47 | //Process.Start(hyperlink.NavigateUri.AbsoluteUri);
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | [assembly: System.Windows.ThemeInfo(System.Windows.ResourceDictionaryLocation.None, System.Windows.ResourceDictionaryLocation.SourceAssembly)]
2 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/DefaultPopupItemContainer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 |
14 | namespace Unicorn.ViewManager
15 | {
16 | public class DefaultPopupItemContainer : PopupItemContainer
17 | {
18 | static DefaultPopupItemContainer()
19 | {
20 | DefaultStyleKeyProperty.OverrideMetadata(typeof(DefaultPopupItemContainer), new FrameworkPropertyMetadata(typeof(DefaultPopupItemContainer)));
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Dialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 |
16 | namespace Unicorn.ViewManager
17 | {
18 | public class Dialog : PopupItem
19 | {
20 | public bool IsDrugMove
21 | {
22 | get
23 | {
24 | return (bool)GetValue(IsDrugMoveProperty);
25 | }
26 | set
27 | {
28 | SetValue(IsDrugMoveProperty, value);
29 | }
30 | }
31 | public static readonly DependencyProperty IsDrugMoveProperty = DependencyProperty.Register("IsDrugMove", typeof(bool), typeof(Dialog), new PropertyMetadata(true));
32 |
33 |
34 | static Dialog()
35 | {
36 | DefaultStyleKeyProperty.OverrideMetadata(typeof(Dialog), new FrameworkPropertyMetadata(typeof(Dialog)));
37 | }
38 |
39 | protected internal override PopupItemContainer GetContainer()
40 | {
41 | return new DialogContainer
42 | {
43 | Dialog = this
44 | };
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/DialogContainer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Media;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using System.Windows;
10 | using System.Windows.Controls;
11 | using System.Windows.Data;
12 | using System.Windows.Documents;
13 | using System.Windows.Input;
14 | using System.Windows.Media;
15 | using System.Windows.Media.Effects;
16 | using System.Windows.Media.Imaging;
17 | using System.Windows.Navigation;
18 | using System.Windows.Shapes;
19 | using Unicorn.Utilities;
20 |
21 | namespace Unicorn.ViewManager
22 | {
23 | internal class DialogContainer : PopupItemContainer
24 | {
25 | public Dialog Dialog
26 | {
27 | get
28 | {
29 | return (Dialog)GetValue(DialogProperty);
30 | }
31 | set
32 | {
33 | SetValue(DialogProperty, value);
34 | }
35 | }
36 | public static readonly DependencyProperty DialogProperty = DependencyProperty.Register("Dialog", typeof(Dialog), typeof(DialogContainer), new PropertyMetadata(null));
37 |
38 | static DialogContainer()
39 | {
40 | DefaultStyleKeyProperty.OverrideMetadata(typeof(DialogContainer), new FrameworkPropertyMetadata(typeof(DialogContainer)));
41 | }
42 |
43 | private Border _border = null;
44 | private Border _funcBorder = null;
45 | private Border _transformBorder = null;
46 | private ContentPresenter _content;
47 | private bool _isTemplateApplyed = false;
48 | public override void OnApplyTemplate()
49 | {
50 | this._border = this.GetTemplateChild("PART_BACKGROUND") as Border;
51 | this._funcBorder = this.GetTemplateChild("_funcBorder") as Border;
52 | this._transformBorder = this.GetTemplateChild("_transformBorder") as Border;
53 | this._content = this.GetTemplateChild("PART_CONTENT") as ContentPresenter;
54 | this._isTemplateApplyed = true;
55 |
56 | this._funcBorder.MouseDown += _funcBorder_MouseDown;
57 |
58 | base.OnApplyTemplate();
59 | }
60 |
61 | private void _funcBorder_MouseDown(object sender, MouseButtonEventArgs e)
62 | {
63 | if (e.OriginalSource == sender
64 | && e.OriginalSource is Border
65 | && !this.PopupItem._isClosing)
66 | {
67 | if (this.PopupItem._showingAsModal)
68 | {
69 | this.Flicker();
70 | }
71 | else if (this.PopupItem.IsEasyClose)
72 | {
73 | this.PopupItem.Close();
74 | }
75 | }
76 |
77 | e.Handled = true;
78 | }
79 |
80 | private void RestoreTransform()
81 | {
82 | if (this._transformBorder != null)
83 | {
84 | this._transformBorder.RenderTransform = null;
85 | }
86 | }
87 |
88 | private bool _isCloseInvoked = false;
89 |
90 | protected internal override void OnShowAnimation(Action callback)
91 | {
92 | this.RestoreTransform();
93 |
94 | if (this._isTemplateApplyed)
95 | {
96 | this._border.Opacity = 0;
97 | this._border.BeginTransformAnimation(new AnimationParameter
98 | {
99 | ControlAnimation = ControlAnimation.ControlOpacityToOne,
100 | Values = new TransformValues(),
101 | StoryboardComplateCallBack = obj =>
102 | {
103 | if (!this._isCloseInvoked)
104 | {
105 | this._border.BeginAnimation(Control.OpacityProperty, null);
106 | this._border.Opacity = 1;
107 | }
108 |
109 | base.OnShowAnimation(callback);
110 | }
111 | });
112 |
113 | var actualwidth = this.ActualWidth == 0 ? this.Dialog.ParentHostStack.ActualWidth : this.ActualWidth;
114 | var actualheigth = this.ActualHeight == 0 ? this.Dialog.ParentHostStack.ActualHeight : this.ActualHeight;
115 |
116 | this._transformBorder.BeginTransformAnimation(new AnimationParameter
117 | {
118 | ControlAnimation = ControlAnimation.ScaleTransformToOne,
119 | Values = new TransformValues
120 | {
121 | ScaleCenterX = actualwidth / 2,
122 | ScaleCenterY = actualheigth / 2,
123 | ScaleFromX = 0.9,
124 | ScaleFromY = 0.9,
125 |
126 | //ScaleFromX = 1.2,
127 | //ScaleFromY = 1.2,
128 | }
129 | });
130 | }
131 | else
132 | {
133 | base.OnShowAnimation(callback);
134 | }
135 | }
136 |
137 | protected internal override void OnCloseAnimation(Action callback)
138 | {
139 | if (this._isCloseInvoked)
140 | {
141 | return;
142 | }
143 | this._isCloseInvoked = true;
144 |
145 | this.RestoreTransform();
146 |
147 | if (this._isTemplateApplyed)
148 | {
149 | this._border.IsHitTestVisible = false;
150 |
151 | this._border.BeginTransformAnimation(new AnimationParameter
152 | {
153 | ControlAnimation = ControlAnimation.ControlOpacityToZero,
154 | Values = new TransformValues(),
155 | StoryboardComplateCallBack = obj =>
156 | {
157 | this._border.BeginAnimation(Control.OpacityProperty, null);
158 | this._border.Opacity = 0;
159 |
160 | base.OnCloseAnimation(callback);
161 | }
162 | });
163 |
164 | var actualwidth = this.ActualWidth == 0 ? this.Dialog.ParentHostStack.ActualWidth : this.ActualWidth;
165 | var actualheigth = this.ActualHeight == 0 ? this.Dialog.ParentHostStack.ActualHeight : this.ActualHeight;
166 |
167 | this._transformBorder.BeginTransformAnimation(new AnimationParameter
168 | {
169 | ControlAnimation = ControlAnimation.ScaleTransformToValue,
170 | Values = new TransformValues
171 | {
172 | ScaleCenterX = actualwidth / 2,
173 | ScaleCenterY = actualheigth / 2,
174 | ScaleToX = 0.9,
175 | ScaleToY = 0.9
176 | }
177 | });
178 | }
179 | else
180 | {
181 | base.OnCloseAnimation(callback);
182 | }
183 | }
184 |
185 | protected async internal override void Flicker()
186 | {
187 | base.Flicker();
188 |
189 | if (this._isTemplateApplyed)
190 | {
191 | DropShadowEffect effect = new DropShadowEffect
192 | {
193 | Color = Colors.Black,
194 | Opacity = 0.8,
195 | ShadowDepth = 0,
196 | BlurRadius = 20
197 | };
198 |
199 | int delay = 40;
200 |
201 | this._content.Effect = effect;
202 | await Task.Delay(delay);
203 | this._content.Effect = null;
204 | await Task.Delay(delay);
205 | this._content.Effect = effect;
206 | await Task.Delay(delay);
207 | this._content.Effect = null;
208 | await Task.Delay(delay);
209 | this._content.Effect = effect;
210 | await Task.Delay(delay);
211 | this._content.Effect = null;
212 | await Task.Delay(delay);
213 | this._content.Effect = effect;
214 | await Task.Delay(delay);
215 | this._content.Effect = null;
216 | await Task.Delay(delay);
217 | this._content.Effect = effect;
218 | await Task.Delay(delay);
219 | this._content.Effect = null;
220 | }
221 | }
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Flyout.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 |
16 | namespace Unicorn.ViewManager
17 | {
18 | public enum FlyoutLocation
19 | {
20 | Left,
21 | Right,
22 | Bottom,
23 | Top
24 | }
25 | public class Flyout : PopupItem
26 | {
27 | public FlyoutLocation FlyoutLocation
28 | {
29 | get
30 | {
31 | return (FlyoutLocation)GetValue(FlyoutLocationProperty);
32 | }
33 | set
34 | {
35 | SetValue(FlyoutLocationProperty, value);
36 | }
37 | }
38 | public static readonly DependencyProperty FlyoutLocationProperty = DependencyProperty.Register("FlyoutLocation", typeof(FlyoutLocation), typeof(Flyout), new PropertyMetadata(FlyoutLocation.Left));
39 |
40 | static Flyout()
41 | {
42 | DefaultStyleKeyProperty.OverrideMetadata(typeof(Flyout), new FrameworkPropertyMetadata(typeof(Flyout)));
43 | }
44 |
45 | protected internal override PopupItemContainer GetContainer()
46 | {
47 | return new FlyoutContainer
48 | {
49 | Flyout = this
50 | };
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/FlyoutContainer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Media;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Navigation;
15 | using System.Windows.Shapes;
16 | using Unicorn.Utilities;
17 |
18 | namespace Unicorn.ViewManager
19 | {
20 | internal class FlyoutContainer : PopupItemContainer
21 | {
22 | public Flyout Flyout
23 | {
24 | get
25 | {
26 | return (Flyout)GetValue(FlyoutProperty);
27 | }
28 | set
29 | {
30 | SetValue(FlyoutProperty, value);
31 | }
32 | }
33 | public static readonly DependencyProperty FlyoutProperty = DependencyProperty.Register("Flyout", typeof(Flyout), typeof(FlyoutContainer), new PropertyMetadata(null));
34 |
35 | static FlyoutContainer()
36 | {
37 | DefaultStyleKeyProperty.OverrideMetadata(typeof(FlyoutContainer), new FrameworkPropertyMetadata(typeof(FlyoutContainer)));
38 | }
39 |
40 | private Grid _grid = null;
41 | private Border _funcBorder = null;
42 | private Border _transformBorder = null;
43 | private ContentPresenter _content;
44 | private bool _isTemplateApplyed = false;
45 | public override void OnApplyTemplate()
46 | {
47 | this._grid = this.GetTemplateChild("PART_BACKGROUND") as Grid;
48 | this._funcBorder = this.GetTemplateChild("_funcBorder") as Border;
49 | this._transformBorder = this.GetTemplateChild("_transformBorder") as Border;
50 | this._content = this.GetTemplateChild("PART_CONTENT") as ContentPresenter;
51 | this._isTemplateApplyed = true;
52 |
53 | this._funcBorder.MouseDown += _funcBorder_MouseDown;
54 |
55 | base.OnApplyTemplate();
56 | }
57 | private void _funcBorder_MouseDown(object sender, MouseButtonEventArgs e)
58 | {
59 | if (e.OriginalSource == sender
60 | && e.OriginalSource is Border
61 | && !this.PopupItem._isClosing)
62 | {
63 | if (this.PopupItem._showingAsModal)
64 | {
65 | this.Flicker();
66 | }
67 | else if (this.PopupItem.IsEasyClose)
68 | {
69 | this.PopupItem.Close();
70 | }
71 | }
72 |
73 | e.Handled = true;
74 | }
75 | private void RestoreTransform()
76 | {
77 | if (this._transformBorder != null)
78 | {
79 | this._transformBorder.RenderTransform = null;
80 | }
81 | }
82 | private double PriorityValue(params double[] values)
83 | {
84 | for (int i = 0; i < values.Length; i++)
85 | {
86 | if (!double.IsNaN(values[i])
87 | && !double.IsInfinity(values[i])
88 | && values[i] > 0)
89 | {
90 | return values[i];
91 | }
92 | }
93 | return 0;
94 | }
95 |
96 | private bool _isCloseInvoked = false;
97 |
98 | protected internal override void OnShowAnimation(Action callback)
99 | {
100 | this.RestoreTransform();
101 |
102 | if (this._isTemplateApplyed)
103 | {
104 | this._grid.Opacity = 0;
105 | this._grid.BeginTransformAnimation(new AnimationParameter
106 | {
107 | ControlAnimation = ControlAnimation.ControlOpacityToOne,
108 | Values = new TransformValues(),
109 | StoryboardComplateCallBack = obj =>
110 | {
111 | if (!this._isCloseInvoked)
112 | {
113 | this._grid.BeginAnimation(Control.OpacityProperty, null);
114 | this._grid.Opacity = 1;
115 | }
116 |
117 | callback?.Invoke(this.PopupItem);
118 | }
119 | });
120 |
121 | double from_x = 0,
122 | from_y = 0;
123 |
124 | switch (this.Flyout.FlyoutLocation)
125 | {
126 | case FlyoutLocation.Left:
127 | from_y = 0;
128 | from_x = -PriorityValue(this.Flyout.MinWidth, this.Flyout.Width, this.Flyout.ActualWidth);
129 | from_x = Math.Max(-100, from_x);
130 | break;
131 |
132 | case FlyoutLocation.Right:
133 | from_y = 0;
134 | from_x = PriorityValue(this.Flyout.MinWidth, this.Flyout.Width, this.Flyout.ActualWidth);
135 | from_x = Math.Min(100, from_x);
136 | break;
137 |
138 | case FlyoutLocation.Bottom:
139 | from_y = PriorityValue(this.Flyout.MinHeight, this.Flyout.Height, this.Flyout.ActualHeight);
140 | from_x = 0;
141 | from_y = Math.Min(100, from_y);
142 | break;
143 |
144 | case FlyoutLocation.Top:
145 | from_y = -PriorityValue(this.Flyout.MinHeight, this.Flyout.Height, this.Flyout.ActualHeight);
146 | from_x = 0;
147 | from_y = Math.Max(-100, from_y);
148 | break;
149 | }
150 |
151 | this._transformBorder.BeginTransformAnimation(new AnimationParameter
152 | {
153 | ControlAnimation = ControlAnimation.TranslateTransformToValue,
154 | Values = new TransformValues
155 | {
156 | TranslateFromX = from_x,
157 | TranslateFromY = from_y,
158 | TranslateToX = 0,
159 | TranslateToY = 0
160 | }
161 | });
162 | }
163 | else
164 | {
165 | callback?.Invoke(this.PopupItem);
166 | }
167 | }
168 |
169 | protected internal override void OnCloseAnimation(Action callback)
170 | {
171 | if (this._isCloseInvoked)
172 | {
173 | return;
174 | }
175 | this._isCloseInvoked = true;
176 |
177 | this.RestoreTransform();
178 |
179 | if (this._isTemplateApplyed)
180 | {
181 | this._grid.IsHitTestVisible = false;
182 |
183 | this._grid.BeginTransformAnimation(new AnimationParameter
184 | {
185 | ControlAnimation = ControlAnimation.ControlOpacityToZero,
186 | Values = new TransformValues(),
187 | StoryboardComplateCallBack = obj =>
188 | {
189 | this._grid.BeginAnimation(Control.OpacityProperty, null);
190 | this._grid.Opacity = 0;
191 |
192 | base.OnCloseAnimation(callback);
193 | }
194 | });
195 |
196 | double to_x = 0,
197 | to_y = 0;
198 |
199 | switch (this.Flyout.FlyoutLocation)
200 | {
201 | case FlyoutLocation.Left:
202 | to_y = 0;
203 | to_x = -PriorityValue(this.Flyout.MinWidth, this.Flyout.Width, this.Flyout.ActualWidth);
204 | to_x = Math.Max(-100, to_x);
205 | break;
206 |
207 | case FlyoutLocation.Right:
208 | to_y = 0;
209 | to_x = PriorityValue(this.Flyout.MinWidth, this.Flyout.Width, this.Flyout.ActualWidth);
210 | to_x = Math.Min(100, to_x);
211 | break;
212 |
213 | case FlyoutLocation.Bottom:
214 | to_y = PriorityValue(this.Flyout.MinHeight, this.Flyout.Height, this.Flyout.ActualHeight);
215 | to_x = 0;
216 | to_y = Math.Min(100, to_y);
217 | break;
218 |
219 | case FlyoutLocation.Top:
220 | to_y = -PriorityValue(this.Flyout.MinHeight, this.Flyout.Height, this.Flyout.ActualHeight);
221 | to_x = 0;
222 | to_y = Math.Max(-100, to_y);
223 | break;
224 | }
225 |
226 | this._transformBorder.BeginTransformAnimation(new AnimationParameter
227 | {
228 | ControlAnimation = ControlAnimation.TranslateTransformToValue,
229 | Values = new TransformValues
230 | {
231 | TranslateFromX = 0,
232 | TranslateFromY = 0,
233 | TranslateToX = to_x,
234 | TranslateToY = to_y
235 | }
236 | });
237 | }
238 | else
239 | {
240 | base.OnCloseAnimation(callback);
241 | }
242 | }
243 |
244 | protected internal override void Flicker()
245 | {
246 | base.Flicker();
247 | }
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/IPopupItemContainer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 |
4 | namespace Unicorn.ViewManager
5 | {
6 | public interface IPopupItemContainer
7 | {
8 | event ViewStackChangedEventHandler ViewStackChanged;
9 |
10 | IPopupItemContainer Parent
11 | {
12 | get;
13 | }
14 |
15 | PopupItem TopItem
16 | {
17 | get;
18 | }
19 |
20 | IEnumerable Children
21 | {
22 | get;
23 | }
24 |
25 | ModalResult ShowModal(PopupItem item);
26 |
27 | void Show(PopupItem item);
28 |
29 | void Close(PopupItem item);
30 |
31 | bool Close();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/ModalResult.cs:
--------------------------------------------------------------------------------
1 | namespace Unicorn.ViewManager
2 | {
3 | public class ModalResult
4 | {
5 | public object Result
6 | {
7 | get; set;
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/PopupItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Interop;
10 | using System.Windows.Media;
11 | using System.Windows.Threading;
12 |
13 | namespace Unicorn.ViewManager
14 | {
15 | [TemplatePart(Name = PART_POPUPSTACK, Type = typeof(ContentPresenter))]
16 | public abstract class PopupItem : ContentControl, IPopupItemContainer
17 | {
18 | const string PART_POPUPSTACK = "PART_POPUPSTACK";
19 |
20 | private static readonly object EVENT_CLOSING = new object();
21 | private static readonly object EVENT_CLOSED = new object();
22 | private static readonly object EVENT_SHOWING = new object();
23 | private static readonly object EVENT_SHOWN = new object();
24 |
25 | internal bool _isHostAtViewStack = false;
26 | internal bool _isClosing = false;
27 | internal bool _isShowing = false;
28 | internal bool _showingAsModal = false;
29 | internal DispatcherFrame _dispatcherFrame = null;
30 | internal ModalResult _modalResult;
31 | private EventHandlerList _events;
32 | private readonly PopupStackControl _childPopupStackControl = null;
33 |
34 | private WeakReference _parentHostContainer = null;
35 | private WeakReference _parentHostStack = null;
36 |
37 | IPopupItemContainer IPopupItemContainer.Parent => this.ParentHostStack;
38 |
39 | public PopupItem TopItem
40 | {
41 | get
42 | {
43 | PopupItem topitem = this.ChildPopupStackControl.TopItem;
44 | if (topitem == null)
45 | {
46 | topitem = this;
47 | }
48 | return topitem;
49 | }
50 | }
51 |
52 | public IEnumerable Children => this.ChildPopupStackControl.Items;
53 |
54 |
55 | public IPopupItemContainer ParentHostContainer
56 | {
57 | get
58 | {
59 | if (this.ParentHostStack != null)
60 | {
61 | return this.ParentHostStack;
62 | }
63 |
64 | this._parentHostContainer.TryGetTarget(out var container);
65 |
66 | return container;
67 | }
68 | }
69 |
70 | internal PopupStackControl ChildPopupStackControl
71 | {
72 | get
73 | {
74 | return this._childPopupStackControl;
75 | }
76 | }
77 |
78 | public event ViewStackChangedEventHandler ViewStackChanged
79 | {
80 | add
81 | {
82 | this.ChildPopupStackControl.ViewStackChanged += value;
83 | }
84 | remove
85 | {
86 | this.ChildPopupStackControl.ViewStackChanged -= value;
87 | }
88 | }
89 |
90 | public ModalResult ModalResult
91 | {
92 | get
93 | {
94 | return _modalResult;
95 | }
96 | set
97 | {
98 | if (!this._showingAsModal)
99 | {
100 | throw new InvalidOperationException($"当前 {this.GetType()} 不作为模态显示,因此不能设置ModalResult");
101 | }
102 | _modalResult = value;
103 | this.Close();
104 | }
105 | }
106 |
107 | private EventHandlerList Events
108 | {
109 | get
110 | {
111 | if (this._events == null)
112 | {
113 | this._events = new EventHandlerList();
114 | }
115 | return this._events;
116 | }
117 | }
118 |
119 | public PopupItem ParentPopup
120 | {
121 | get;
122 | internal set;
123 | }
124 |
125 | public bool IsEasyClose
126 | {
127 | get
128 | {
129 | return (bool)GetValue(IsEasyCloseProperty);
130 | }
131 | set
132 | {
133 | SetValue(IsEasyCloseProperty, value);
134 | }
135 | }
136 | public static readonly DependencyProperty IsEasyCloseProperty = DependencyProperty.Register("IsEasyClose", typeof(bool), typeof(PopupItem), new PropertyMetadata(false));
137 |
138 |
139 | public event CancelEventHandler Showing
140 | {
141 | add
142 | {
143 | this.Events.AddHandler(PopupItem.EVENT_SHOWING, (Delegate)value);
144 | }
145 | remove
146 | {
147 | this.Events.RemoveHandler(PopupItem.EVENT_SHOWING, (Delegate)value);
148 | }
149 | }
150 | public event EventHandler Shown
151 | {
152 | add
153 | {
154 | this.Events.AddHandler(PopupItem.EVENT_SHOWN, (Delegate)value);
155 | }
156 | remove
157 | {
158 | this.Events.RemoveHandler(PopupItem.EVENT_SHOWN, (Delegate)value);
159 | }
160 | }
161 |
162 | public event CancelEventHandler Closing
163 | {
164 | add
165 | {
166 | this.Events.AddHandler(PopupItem.EVENT_CLOSING, (Delegate)value);
167 | }
168 | remove
169 | {
170 | this.Events.RemoveHandler(PopupItem.EVENT_CLOSING, (Delegate)value);
171 | }
172 | }
173 |
174 | public event EventHandler Closed
175 | {
176 | add
177 | {
178 | this.Events.AddHandler(PopupItem.EVENT_CLOSED, (Delegate)value);
179 | }
180 | remove
181 | {
182 | this.Events.RemoveHandler(PopupItem.EVENT_CLOSED, (Delegate)value);
183 | }
184 | }
185 |
186 | public PopupItem()
187 | {
188 | this._childPopupStackControl = new PopupStackControl(this);
189 | }
190 |
191 | public override void OnApplyTemplate()
192 | {
193 | base.OnApplyTemplate();
194 |
195 | var presenter = this.GetTemplateChild(PART_POPUPSTACK) as ContentPresenter;
196 |
197 | if (presenter != null)
198 | {
199 | presenter.Content = this._childPopupStackControl;
200 | }
201 | }
202 |
203 | #region Events
204 |
205 | internal void InternalShowing(out CancelEventArgs e)
206 | {
207 | e = new CancelEventArgs(false);
208 | this.OnShowing(e);
209 | }
210 |
211 | protected virtual void OnShowing(CancelEventArgs e)
212 | {
213 | CancelEventHandler cancelEventHandler = (CancelEventHandler)this.Events[PopupItem.EVENT_SHOWING];
214 | if (cancelEventHandler == null)
215 | return;
216 | cancelEventHandler((object)this, e);
217 | }
218 |
219 | internal void InternalShown(out EventArgs e)
220 | {
221 | e = new EventArgs();
222 | this.OnShown(e);
223 | }
224 |
225 | protected virtual void OnShown(EventArgs e)
226 | {
227 | EventHandler eventHandler = (EventHandler)this.Events[PopupItem.EVENT_SHOWN];
228 | if (eventHandler == null)
229 | return;
230 | eventHandler((object)this, e);
231 | }
232 |
233 | internal void InternalClosing(out CancelEventArgs e)
234 | {
235 | e = new CancelEventArgs(false);
236 | this.OnClosing(e);
237 | }
238 |
239 | protected virtual void OnClosing(CancelEventArgs e)
240 | {
241 | CancelEventHandler cancelEventHandler = (CancelEventHandler)this.Events[PopupItem.EVENT_CLOSING];
242 | if (cancelEventHandler == null)
243 | return;
244 | cancelEventHandler((object)this, e);
245 | }
246 |
247 | internal void InternalClosed(out EventArgs e)
248 | {
249 | e = new EventArgs();
250 | this.OnClosed(e);
251 | }
252 |
253 | protected virtual void OnClosed(EventArgs e)
254 | {
255 | EventHandler eventHandler = (EventHandler)this.Events[PopupItem.EVENT_CLOSED];
256 | if (eventHandler == null)
257 | return;
258 | eventHandler((object)this, e);
259 | }
260 |
261 | #endregion
262 |
263 | internal PopupStackControl ParentHostStack
264 | {
265 | get
266 | {
267 | this._parentHostStack.TryGetTarget(out var parenthost);
268 | return parenthost;
269 | }
270 | set
271 | {
272 | this._parentHostStack = new WeakReference(value);
273 | this._parentHostContainer = new WeakReference(value);
274 | }
275 | }
276 |
277 |
278 |
279 | #region Show Self
280 |
281 | public void Show()
282 | {
283 | ViewManager.Instance.ActiveContainer.Show(this);
284 | }
285 |
286 | public void Show(IPopupItemContainer container)
287 | {
288 | if (container == null)
289 | {
290 | throw new ArgumentNullException(nameof(container));
291 | }
292 |
293 | var oldcontainer = this._parentHostContainer;
294 | this._parentHostContainer = new WeakReference(container);
295 | try
296 | {
297 | container.Show(this);
298 | }
299 | catch (Exception)
300 | {
301 | this._parentHostContainer = oldcontainer;
302 | throw;
303 | }
304 | }
305 |
306 | public ModalResult ShowAsModal()
307 | {
308 | return ViewManager.Instance.ActiveContainer.ShowModal(this);
309 | }
310 | public ModalResult ShowAsModal(IPopupItemContainer container)
311 | {
312 | if (container == null)
313 | {
314 | throw new ArgumentNullException(nameof(container));
315 | }
316 |
317 | var oldcontainer = this._parentHostContainer;
318 | this._parentHostContainer = new WeakReference(container);
319 | try
320 | {
321 | return container.ShowModal(this);
322 | }
323 | catch (Exception)
324 | {
325 | this._parentHostContainer = oldcontainer;
326 | throw;
327 | }
328 | }
329 |
330 | public void Close()
331 | {
332 | if (this.ParentHostStack != null)
333 | {
334 | this.ParentHostStack.Close(this);
335 | }
336 | }
337 |
338 | #endregion
339 |
340 |
341 | #region Show Child
342 | public ModalResult ShowModal(PopupItem item)
343 | {
344 | if (item == null)
345 | {
346 | throw new ArgumentNullException(nameof(item));
347 | }
348 |
349 | return this._childPopupStackControl.ShowModal(item);
350 | }
351 |
352 | public void Show(PopupItem item)
353 | {
354 | if (item == null)
355 | {
356 | throw new ArgumentNullException(nameof(item));
357 | }
358 |
359 | this._childPopupStackControl.Show(item);
360 | }
361 |
362 | public void Close(PopupItem item)
363 | {
364 | this._childPopupStackControl.Close(item);
365 | }
366 |
367 | #endregion
368 |
369 | internal void InternalDiapose()
370 | {
371 | this.ParentHostStack = null;
372 | this._isClosing = false;
373 | this._isHostAtViewStack = false;
374 | this.ParentPopup = null;
375 |
376 | if (this._dispatcherFrame != null)
377 | {
378 | this._dispatcherFrame.Continue = false;
379 | }
380 |
381 | this._dispatcherFrame = null;
382 | this._showingAsModal = false;
383 | }
384 |
385 | bool IPopupItemContainer.Close()
386 | {
387 | return this._childPopupStackControl.Close();
388 | }
389 |
390 | protected internal abstract PopupItemContainer GetContainer();
391 |
392 |
393 |
394 |
395 | public IPopupItemContainer FindParentHost()
396 | {
397 | return ViewTreeHelper.FindParent(this);
398 | }
399 | }
400 |
401 |
402 | internal static class ViewTreeHelper
403 | {
404 | public static T FindParent(FrameworkElement element) where T : class
405 | {
406 | if (element == null)
407 | {
408 | return null;
409 | }
410 |
411 | FrameworkElement parent = VisualTreeHelper.GetParent(element) as FrameworkElement;
412 | if (parent == null)
413 | {
414 | parent = LogicalTreeHelper.GetParent(element) as FrameworkElement;
415 | }
416 |
417 | while (parent != null
418 | && !(parent is T)
419 | && !(parent is Window))
420 | {
421 | var temp = VisualTreeHelper.GetParent(parent) as FrameworkElement;
422 |
423 | if (temp == null)
424 | {
425 | temp = LogicalTreeHelper.GetParent(parent) as FrameworkElement;
426 | }
427 |
428 | parent = temp;
429 | }
430 |
431 | return parent as T;
432 | }
433 | }
434 | }
435 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/PopupItemContainer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Media;
3 | using System.Windows;
4 | using System.Windows.Controls;
5 | using Unicorn.ViewManager.Preferences;
6 |
7 | namespace Unicorn.ViewManager
8 | {
9 | public class PopupItemContainer : Control
10 | {
11 | public PopupItem PopupItem
12 | {
13 | get
14 | {
15 | return (PopupItem)GetValue(PopupItemProperty);
16 | }
17 | set
18 | {
19 | SetValue(PopupItemProperty, value);
20 | }
21 | }
22 | public static readonly DependencyProperty PopupItemProperty = DependencyProperty.Register("PopupItem", typeof(PopupItem), typeof(PopupItemContainer), new PropertyMetadata(null));
23 |
24 | static PopupItemContainer()
25 | {
26 | DefaultStyleKeyProperty.OverrideMetadata(typeof(PopupItemContainer), new FrameworkPropertyMetadata(typeof(PopupItemContainer)));
27 | }
28 |
29 | private bool _isTemplateApply = false;
30 | private bool _isShowAnimationRequest = false;
31 | public override void OnApplyTemplate()
32 | {
33 | base.OnApplyTemplate();
34 |
35 | this._isTemplateApply = true;
36 |
37 | if (this._isShowAnimationRequest)
38 | {
39 | this._isShowAnimationRequest = false;
40 | this._requestCallback = _p =>
41 | {
42 | try
43 | {
44 | this._callback?.Invoke(_p);
45 |
46 | }
47 | finally
48 | {
49 | this._callback = null;
50 | this._requestCallback = null;
51 | }
52 | };
53 |
54 | this.OnShowAnimation(this._requestCallback);
55 | }
56 | }
57 |
58 | private Action _requestCallback = null;
59 | private Action _callback = null;
60 | internal void RequestShowAnimation(Action callback)
61 | {
62 | if (this._isTemplateApply)
63 | {
64 | this.OnShowAnimation(callback);
65 | }
66 | else
67 | {
68 | this._callback = callback;
69 | this._isShowAnimationRequest = true;
70 | }
71 | }
72 |
73 | protected internal virtual void OnShowAnimation(Action callback)
74 | {
75 | callback?.Invoke(this.PopupItem);
76 | }
77 |
78 | protected internal virtual void Flicker()
79 | {
80 | SystemSounds.Beep.Play();
81 | }
82 |
83 | protected internal virtual void OnCloseAnimation(Action callback)
84 | {
85 | callback?.Invoke(this.PopupItem);
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/PopupStack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Collections.Specialized;
5 | using System.ComponentModel;
6 | using System.Linq;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Interop;
10 | using System.Windows.Threading;
11 |
12 | namespace Unicorn.ViewManager
13 | {
14 | internal class PopupStack : ItemsControl
15 | {
16 | static PopupStack()
17 | {
18 | DefaultStyleKeyProperty.OverrideMetadata(typeof(PopupStack), new FrameworkPropertyMetadata(typeof(PopupStack)));
19 | }
20 |
21 | private readonly PopupStackControl _parentPopupStackControl = null;
22 |
23 | public PopupStack(PopupStackControl popupStackControl)
24 | {
25 | if (popupStackControl == null)
26 | {
27 | throw new ArgumentNullException(nameof(popupStackControl));
28 | }
29 |
30 | this._parentPopupStackControl = popupStackControl;
31 | }
32 |
33 | protected override bool IsItemItsOwnContainerOverride(object item)
34 | {
35 | return item is PopupItemContainer;
36 | }
37 |
38 | protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
39 | {
40 | base.OnItemsChanged(e);
41 |
42 | this._parentPopupStackControl.OnViewStackChanged(
43 | new ViewStackChangedEventArgs(
44 | (ViewStackAction)(int)(e.Action),
45 | e.NewItems?.OfType()?.ToList(),
46 | e.NewStartingIndex,
47 | e.OldItems?.OfType()?.ToList(),
48 | e.OldStartingIndex
49 | ));
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Preferences/ViewPreferences.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 |
6 | namespace Unicorn.ViewManager.Preferences
7 | {
8 | public sealed class ViewPreferences : DependencyObject
9 | {
10 | private static ViewPreferences _instance = null;
11 | public static ViewPreferences Instance
12 | {
13 | get
14 | {
15 | if (_instance == null)
16 | {
17 | _instance = new ViewPreferences();
18 | }
19 | return _instance;
20 | }
21 | }
22 |
23 | private ViewPreferences()
24 | {
25 |
26 | }
27 |
28 | public bool UsePopupViewAnimations
29 | {
30 | get
31 | {
32 | return (bool)GetValue(UsePopupViewAnimationsProperty);
33 | }
34 | set
35 | {
36 | SetValue(UsePopupViewAnimationsProperty, value);
37 | }
38 | }
39 | public static readonly DependencyProperty UsePopupViewAnimationsProperty = DependencyProperty.Register("UsePopupViewAnimations", typeof(bool), typeof(ViewPreferences), new PropertyMetadata(true));
40 |
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Resource/Images/box_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrZhangYuan/Unicorn.ViewManager/312e86538393817302cdaa7b1e22c66aeb2c5be4/src/Unicorn.ViewManager/Resource/Images/box_error.png
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Resource/Images/box_info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrZhangYuan/Unicorn.ViewManager/312e86538393817302cdaa7b1e22c66aeb2c5be4/src/Unicorn.ViewManager/Resource/Images/box_info.png
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Resource/Images/box_question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrZhangYuan/Unicorn.ViewManager/312e86538393817302cdaa7b1e22c66aeb2c5be4/src/Unicorn.ViewManager/Resource/Images/box_question.png
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Resource/Images/box_warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MrZhangYuan/Unicorn.ViewManager/312e86538393817302cdaa7b1e22c66aeb2c5be4/src/Unicorn.ViewManager/Resource/Images/box_warning.png
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/RichViewControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Controls.Primitives;
7 | using System.Windows.Data;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Navigation;
13 | using System.Windows.Shapes;
14 | using Unicorn.Utilities;
15 |
16 | namespace Unicorn.ViewManager
17 | {
18 | public interface IRichViewContainer
19 | {
20 | void ShowView(object item);
21 | void CloseView(object item);
22 | void SwitchView(object item);
23 | }
24 |
25 | [TemplatePart(Name = PART_POPUPSTACKCONTROL, Type = typeof(ContentPresenter))]
26 | public class RichViewControl : ItemsControl, IRichViewContainer, IPopupItemContainer
27 | {
28 | private const string PART_POPUPSTACKCONTROL = "PART_POPUPSTACKCONTROL";
29 |
30 | private readonly PopupStackControl _popupStackControl = null;
31 |
32 | public PopupStackControl PopupStackControl
33 | {
34 | get
35 | {
36 | return this._popupStackControl;
37 | }
38 | }
39 |
40 | public PopupItem TopItem => this.PopupStackControl.TopItem;
41 |
42 | IPopupItemContainer IPopupItemContainer.Parent => ((IPopupItemContainer)this.PopupStackControl).Parent;
43 |
44 | public IEnumerable Children => this.PopupStackControl.Children;
45 |
46 | public event ViewStackChangedEventHandler ViewStackChanged
47 | {
48 | add
49 | {
50 | this.PopupStackControl.ViewStackChanged += value;
51 | }
52 | remove
53 | {
54 | this.PopupStackControl.ViewStackChanged -= value;
55 | }
56 | }
57 |
58 | public bool IsAnimationActive
59 | {
60 | get
61 | {
62 | return (bool)GetValue(IsAnimationActiveProperty);
63 | }
64 | set
65 | {
66 | SetValue(IsAnimationActiveProperty, value);
67 | }
68 | }
69 | public static readonly DependencyProperty IsAnimationActiveProperty = ProgressRing.IsAnimationActiveProperty.AddOwner(typeof(RichViewControl), new PropertyMetadata(false));
70 |
71 |
72 | static RichViewControl()
73 | {
74 | DefaultStyleKeyProperty.OverrideMetadata(typeof(RichViewControl), new FrameworkPropertyMetadata(typeof(RichViewControl)));
75 | CommandManager.RegisterClassCommandBinding(typeof(RichViewControl), new CommandBinding(ViewCommands.ShowView, new ExecutedRoutedEventHandler(RichViewControl.OnShowView), new CanExecuteRoutedEventHandler(RichViewControl.OnCanShowView)));
76 | CommandManager.RegisterClassCommandBinding(typeof(RichViewControl), new CommandBinding(ViewCommands.CloseView, new ExecutedRoutedEventHandler(RichViewControl.OnCloseView), new CanExecuteRoutedEventHandler(RichViewControl.OnCanCloseView)));
77 | CommandManager.RegisterClassCommandBinding(typeof(RichViewControl), new CommandBinding(ViewCommands.SwitchView, new ExecutedRoutedEventHandler(RichViewControl.OnSwitchView), new CanExecuteRoutedEventHandler(RichViewControl.OnCanSwitchView)));
78 | }
79 |
80 | public RichViewControl()
81 | {
82 | this._popupStackControl = new PopupStackControl();
83 | }
84 |
85 | public override void OnApplyTemplate()
86 | {
87 | base.OnApplyTemplate();
88 |
89 | var contentPresenter = GetTemplateChild(PART_POPUPSTACKCONTROL) as ContentPresenter;
90 |
91 | if (contentPresenter != null)
92 | {
93 | contentPresenter.Content = this._popupStackControl;
94 | }
95 | }
96 |
97 | protected override bool IsItemItsOwnContainerOverride(object item)
98 | {
99 | return item is RichViewItem;
100 | }
101 |
102 | protected override DependencyObject GetContainerForItemOverride()
103 | {
104 | return new RichViewItem();
105 | }
106 |
107 | public ModalResult ShowModal(PopupItem item)
108 | {
109 | return this._popupStackControl.ShowModal(item);
110 | }
111 |
112 | public void Show(PopupItem item)
113 | {
114 | this._popupStackControl.Show(item);
115 | }
116 |
117 | public void Close(PopupItem item)
118 | {
119 | this._popupStackControl.Close(item);
120 | }
121 |
122 | public void ShowView(object item)
123 | {
124 | if (item == null)
125 | {
126 | throw new ArgumentNullException(nameof(item));
127 | }
128 |
129 | if (!this.Items.Contains(item))
130 | {
131 | this.Items.Add(item);
132 | }
133 | }
134 |
135 | public void CloseView(object item)
136 | {
137 | if (item != null)
138 | {
139 | this.Items.Remove(item);
140 | }
141 | }
142 |
143 | public void SwitchView(object item)
144 | {
145 | if (item == null)
146 | {
147 | throw new ArgumentNullException(nameof(item));
148 | }
149 |
150 | this.ShowView(item);
151 |
152 | if (this.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
153 | {
154 | foreach (var view in this.Items)
155 | {
156 | var container = this.ItemContainerGenerator.ContainerFromItem(view) as Control;
157 |
158 | if (object.ReferenceEquals(view, item))
159 | {
160 | container.Visibility = Visibility.Visible;
161 | }
162 | else
163 | {
164 | container.Visibility = Visibility.Hidden;
165 | }
166 | }
167 | }
168 | }
169 |
170 | private static void OnCanShowView(object sender, CanExecuteRoutedEventArgs e)
171 | {
172 | e.CanExecute = e.Parameter != null;
173 | e.Handled = true;
174 | }
175 |
176 | private static void OnShowView(object sender, ExecutedRoutedEventArgs e)
177 | {
178 | ((RichViewControl)sender).ShowView(e.Parameter);
179 | }
180 |
181 | private static void OnCanCloseView(object sender, CanExecuteRoutedEventArgs e)
182 | {
183 | e.CanExecute = e.Parameter != null;
184 | e.Handled = true;
185 | }
186 |
187 | private static void OnCloseView(object sender, ExecutedRoutedEventArgs e)
188 | {
189 | ((RichViewControl)sender).CloseView(e.Parameter);
190 | }
191 |
192 | private static void OnCanSwitchView(object sender, CanExecuteRoutedEventArgs e)
193 | {
194 | e.CanExecute = e.Parameter != null;
195 | e.Handled = true;
196 | }
197 |
198 | private static void OnSwitchView(object sender, ExecutedRoutedEventArgs e)
199 | {
200 | ((RichViewControl)sender).SwitchView(e.Parameter);
201 | }
202 |
203 | public bool Close()
204 | {
205 | return this._popupStackControl.Close();
206 | }
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/RichViewItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 |
14 | namespace Unicorn.ViewManager
15 | {
16 | internal class RichViewItem : ContentControl
17 | {
18 | static RichViewItem()
19 | {
20 | DefaultStyleKeyProperty.OverrideMetadata(typeof(RichViewItem), new FrameworkPropertyMetadata(typeof(RichViewItem)));
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/RichViewWindow.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 | using Unicorn.Utilities;
14 |
15 | namespace Unicorn.ViewManager
16 | {
17 | [TemplatePart(Name = PART_RICHVIEWCONTROL, Type = typeof(ContentPresenter))]
18 | public class RichViewWindow : CustomChromeWindow, IPopupItemContainer
19 | {
20 | private const string PART_RICHVIEWCONTROL = "PART_RICHVIEWCONTROL";
21 |
22 | private readonly RichViewControl _richViewControl = new RichViewControl();
23 |
24 | public RichViewControl RichViewControl
25 | {
26 | get
27 | {
28 | return this._richViewControl;
29 | }
30 | }
31 |
32 | public PopupItem TopItem => this._richViewControl.TopItem;
33 |
34 | IPopupItemContainer IPopupItemContainer.Parent => null;
35 |
36 | public IEnumerable Children => this._richViewControl.Children;
37 |
38 | public event ViewStackChangedEventHandler ViewStackChanged
39 | {
40 | add
41 | {
42 | this.RichViewControl.ViewStackChanged += value;
43 | }
44 | remove
45 | {
46 | this.RichViewControl.ViewStackChanged -= value;
47 | }
48 | }
49 |
50 | public object Header
51 | {
52 | get
53 | {
54 | return (object)GetValue(HeaderProperty);
55 | }
56 | set
57 | {
58 | SetValue(HeaderProperty, value);
59 | }
60 | }
61 | public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(object), typeof(RichViewWindow), new PropertyMetadata(null));
62 |
63 | static RichViewWindow()
64 | {
65 | DefaultStyleKeyProperty.OverrideMetadata(typeof(RichViewWindow), new FrameworkPropertyMetadata(typeof(RichViewWindow)));
66 | }
67 |
68 | public override void OnApplyTemplate()
69 | {
70 | base.OnApplyTemplate();
71 |
72 | var persenter = this.GetTemplateChild(PART_RICHVIEWCONTROL) as ContentPresenter;
73 | if (persenter != null)
74 | {
75 | persenter.Content = this._richViewControl;
76 | }
77 | }
78 |
79 | public void Close(PopupItem item)
80 | {
81 | this._richViewControl.Close(item);
82 | }
83 |
84 | bool IPopupItemContainer.Close()
85 | {
86 | return this._richViewControl.Close();
87 | }
88 |
89 | public void Show(PopupItem item)
90 | {
91 | this._richViewControl.Show(item);
92 | }
93 |
94 | public ModalResult ShowModal(PopupItem item)
95 | {
96 | return this._richViewControl.ShowModal(item);
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/System/Windows/MessageDialogBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Data;
7 | using System.Windows.Documents;
8 | using System.Windows.Input;
9 | using System.Windows.Media;
10 | using System.Windows.Media.Imaging;
11 | using System.Windows.Navigation;
12 | using System.Windows.Shapes;
13 | using System.Windows.Threading;
14 | using Unicorn.ViewManager;
15 |
16 | namespace System.Windows
17 | {
18 | [TemplatePart(Name = PART_CLOSEBUTTON, Type = typeof(Button))]
19 | [TemplatePart(Name = PART_OKBUTTON, Type = typeof(Button))]
20 | [TemplatePart(Name = PART_YESBUTTON, Type = typeof(Button))]
21 | [TemplatePart(Name = PART_NOBUTTON, Type = typeof(Button))]
22 | [TemplatePart(Name = PART_CANCELBUTTON, Type = typeof(Button))]
23 | public sealed class MessageDialogBox : Dialog
24 | {
25 | private const string PART_CLOSEBUTTON = "PART_CLOSEBUTTON";
26 | private const string PART_OKBUTTON = "PART_OKBUTTON";
27 | private const string PART_YESBUTTON = "PART_YESBUTTON";
28 | private const string PART_NOBUTTON = "PART_NOBUTTON";
29 | private const string PART_CANCELBUTTON = "PART_CANCELBUTTON";
30 |
31 |
32 | private IPopupItemContainer _owner = null;
33 |
34 | public string Caption
35 | {
36 | get
37 | {
38 | return (string)GetValue(CaptionProperty);
39 | }
40 | private set
41 | {
42 | SetValue(CaptionProperty, value);
43 | }
44 | }
45 | public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(string), typeof(MessageDialogBox), new PropertyMetadata(string.Empty));
46 |
47 | public string MessageText
48 | {
49 | get
50 | {
51 | return (string)GetValue(MessageTextProperty);
52 | }
53 | private set
54 | {
55 | SetValue(MessageTextProperty, value);
56 | }
57 | }
58 | public static readonly DependencyProperty MessageTextProperty = DependencyProperty.Register("MessageText", typeof(string), typeof(MessageDialogBox), new PropertyMetadata(string.Empty));
59 |
60 | public MessageBoxButton MessageBoxButton
61 | {
62 | get
63 | {
64 | return (MessageBoxButton)GetValue(MessageBoxButtonProperty);
65 | }
66 | private set
67 | {
68 | SetValue(MessageBoxButtonProperty, value);
69 | }
70 | }
71 | public static readonly DependencyProperty MessageBoxButtonProperty = DependencyProperty.Register("MessageBoxButton", typeof(MessageBoxButton), typeof(MessageDialogBox), new PropertyMetadata(MessageBoxButton.OK, MessageBoxButtonPropertyChangedCallBack));
72 |
73 | public MessageBoxImage MessageBoxImage
74 | {
75 | get
76 | {
77 | return (MessageBoxImage)GetValue(MessageBoxImageProperty);
78 | }
79 | private set
80 | {
81 | SetValue(MessageBoxImageProperty, value);
82 | }
83 | }
84 | public static readonly DependencyProperty MessageBoxImageProperty = DependencyProperty.Register("MessageBoxImage", typeof(MessageBoxImage), typeof(MessageDialogBox), new PropertyMetadata(MessageBoxImage.None));
85 |
86 | public MessageBoxResult DefaultResult
87 | {
88 | get
89 | {
90 | return (MessageBoxResult)GetValue(DefaultResultProperty);
91 | }
92 | private set
93 | {
94 | SetValue(DefaultResultProperty, value);
95 | }
96 | }
97 | public static readonly DependencyProperty DefaultResultProperty = DependencyProperty.Register("DefaultResult", typeof(MessageBoxResult), typeof(MessageDialogBox), new PropertyMetadata(MessageBoxResult.None));
98 |
99 | public MessageBoxOptions MessageBoxOptions
100 | {
101 | get
102 | {
103 | return (MessageBoxOptions)GetValue(MessageBoxOptionsProperty);
104 | }
105 | private set
106 | {
107 | SetValue(MessageBoxOptionsProperty, value);
108 | }
109 | }
110 | public static readonly DependencyProperty MessageBoxOptionsProperty = DependencyProperty.Register("MessageBoxOptions", typeof(MessageBoxOptions), typeof(MessageDialogBox), new PropertyMetadata(MessageBoxOptions.None));
111 |
112 | static MessageDialogBox()
113 | {
114 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MessageDialogBox), new FrameworkPropertyMetadata(typeof(MessageDialogBox)));
115 | }
116 |
117 | private MessageDialogBox()
118 | {
119 |
120 | }
121 |
122 | private Button _closeBt = null,
123 | _okBt = null,
124 | _yesBt = null,
125 | _noBt = null,
126 | _cancelBt = null;
127 | private bool _isTemplateApply = false;
128 | public override void OnApplyTemplate()
129 | {
130 | base.OnApplyTemplate();
131 |
132 | _closeBt = this.GetTemplateChild(PART_CLOSEBUTTON) as Button;
133 | _okBt = this.GetTemplateChild(PART_OKBUTTON) as Button;
134 | _yesBt = this.GetTemplateChild(PART_YESBUTTON) as Button;
135 | _noBt = this.GetTemplateChild(PART_NOBUTTON) as Button;
136 | _cancelBt = this.GetTemplateChild(PART_CANCELBUTTON) as Button;
137 |
138 | if (this._closeBt == null
139 | || this._okBt == null
140 | || this._yesBt == null
141 | || this._noBt == null
142 | || this._cancelBt == null)
143 | {
144 | throw new Exception($"模板缺少必须元素{PART_CLOSEBUTTON}、{PART_OKBUTTON}、{PART_YESBUTTON}、{PART_NOBUTTON}、{PART_CANCELBUTTON}一个或多个");
145 | }
146 |
147 | this._isTemplateApply = true;
148 |
149 | this.RefreshMessageBoxButtonVisibility();
150 |
151 | this._closeBt.Click += (sender, e) =>
152 | {
153 | if (this.ValidateButtonUsed(_BoxButton.Close))
154 | {
155 | this.ModalResult = new ModalResult { Result = this.ConverterDefaultResult() };
156 | }
157 | };
158 | this._okBt.Click += (sender, e) =>
159 | {
160 | if (this.ValidateButtonUsed(_BoxButton.OK))
161 | {
162 | this.ModalResult = new ModalResult { Result = MessageBoxResult.OK };
163 | }
164 | };
165 | this._yesBt.Click += (sender, e) =>
166 | {
167 | if (this.ValidateButtonUsed(_BoxButton.Yes))
168 | {
169 | this.ModalResult = new ModalResult { Result = MessageBoxResult.Yes };
170 | }
171 | };
172 | this._noBt.Click += (sender, e) =>
173 | {
174 | if (this.ValidateButtonUsed(_BoxButton.No))
175 | {
176 | this.ModalResult = new ModalResult { Result = MessageBoxResult.No };
177 | }
178 | };
179 | this._cancelBt.Click += (sender, e) =>
180 | {
181 | if (this.ValidateButtonUsed(_BoxButton.Cancel))
182 | {
183 | this.ModalResult = new ModalResult { Result = MessageBoxResult.Cancel };
184 | }
185 | };
186 | }
187 |
188 | private static void MessageBoxButtonPropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
189 | {
190 | ((MessageDialogBox)d).RefreshMessageBoxButtonVisibility();
191 | }
192 |
193 | private enum _BoxButton
194 | {
195 | Close,
196 | OK,
197 | Yes,
198 | No,
199 | Cancel
200 | }
201 | private void RefreshMessageBoxButtonVisibility()
202 | {
203 | if (this._isTemplateApply)
204 | {
205 | switch (this.MessageBoxButton)
206 | {
207 | case MessageBoxButton.OK:
208 | this._okBt.Visibility = Visibility.Visible;
209 | this._okBt.IsEnabled = true;
210 | this._closeBt.Visibility = Visibility.Visible;
211 | this._closeBt.IsEnabled = true;
212 |
213 | this._yesBt.Visibility = Visibility.Collapsed;
214 | this._yesBt.IsEnabled = false;
215 | this._noBt.Visibility = Visibility.Collapsed;
216 | this._noBt.IsEnabled = false;
217 | this._cancelBt.Visibility = Visibility.Collapsed;
218 | this._cancelBt.IsEnabled = false;
219 | break;
220 |
221 | case MessageBoxButton.OKCancel:
222 | this._okBt.Visibility = Visibility.Visible;
223 | this._okBt.IsEnabled = true;
224 | this._closeBt.Visibility = Visibility.Visible;
225 | this._closeBt.IsEnabled = true;
226 | this._cancelBt.Visibility = Visibility.Visible;
227 | this._cancelBt.IsEnabled = true;
228 |
229 | this._yesBt.Visibility = Visibility.Collapsed;
230 | this._yesBt.IsEnabled = false;
231 | this._noBt.Visibility = Visibility.Collapsed;
232 | this._noBt.IsEnabled = false;
233 | break;
234 |
235 | case MessageBoxButton.YesNoCancel:
236 | this._yesBt.Visibility = Visibility.Visible;
237 | this._yesBt.IsEnabled = true;
238 | this._noBt.Visibility = Visibility.Visible;
239 | this._noBt.IsEnabled = true;
240 | this._closeBt.Visibility = Visibility.Visible;
241 | this._closeBt.IsEnabled = true;
242 | this._cancelBt.Visibility = Visibility.Visible;
243 | this._cancelBt.IsEnabled = true;
244 |
245 | this._okBt.Visibility = Visibility.Collapsed;
246 | this._okBt.IsEnabled = false;
247 | break;
248 |
249 | case MessageBoxButton.YesNo:
250 | this._yesBt.Visibility = Visibility.Visible;
251 | this._yesBt.IsEnabled = true;
252 | this._noBt.Visibility = Visibility.Visible;
253 | this._noBt.IsEnabled = true;
254 |
255 | this._closeBt.Visibility = Visibility.Collapsed;
256 | this._closeBt.IsEnabled = false;
257 | this._cancelBt.Visibility = Visibility.Collapsed;
258 | this._cancelBt.IsEnabled = false;
259 | this._okBt.Visibility = Visibility.Collapsed;
260 | this._okBt.IsEnabled = false;
261 | break;
262 | }
263 | }
264 | }
265 |
266 | private bool ValidateButtonUsed(_BoxButton button)
267 | {
268 | switch (button)
269 | {
270 | case _BoxButton.Close:
271 | return this.MessageBoxButton != MessageBoxButton.YesNo;
272 |
273 | case _BoxButton.OK:
274 | return this.MessageBoxButton == MessageBoxButton.OK
275 | || this.MessageBoxButton == MessageBoxButton.OKCancel;
276 |
277 | case _BoxButton.Yes:
278 | return this.MessageBoxButton == MessageBoxButton.YesNo
279 | || this.MessageBoxButton == MessageBoxButton.YesNoCancel;
280 |
281 | case _BoxButton.No:
282 | return this.MessageBoxButton == MessageBoxButton.YesNo
283 | || this.MessageBoxButton == MessageBoxButton.YesNoCancel;
284 |
285 | case _BoxButton.Cancel:
286 | return this.MessageBoxButton == MessageBoxButton.OKCancel
287 | || this.MessageBoxButton == MessageBoxButton.YesNoCancel;
288 | }
289 |
290 | return false;
291 | }
292 |
293 | private MessageBoxResult ConverterDefaultResult()
294 | {
295 | MessageBoxResult result = MessageBoxResult.Cancel;
296 |
297 | switch (this.MessageBoxButton)
298 | {
299 | case MessageBoxButton.OK:
300 | result = MessageBoxResult.OK;
301 | break;
302 |
303 | case MessageBoxButton.OKCancel:
304 | result = MessageBoxResult.Cancel;
305 | break;
306 |
307 | case MessageBoxButton.YesNoCancel:
308 | result = MessageBoxResult.Cancel;
309 | break;
310 |
311 | case MessageBoxButton.YesNo:
312 | result = MessageBoxResult.No;
313 | break;
314 | }
315 |
316 | return result;
317 | }
318 |
319 | public static MessageBoxResult Show(string messageBoxText)
320 | {
321 | return ShowCore(null, messageBoxText, null, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None, MessageBoxOptions.None);
322 | }
323 | public static MessageBoxResult Show(string messageBoxText, string caption)
324 | {
325 | return ShowCore(null, messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None, MessageBoxOptions.None);
326 | }
327 | public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button)
328 | {
329 | return ShowCore(null, messageBoxText, caption, button, MessageBoxImage.None, MessageBoxResult.None, MessageBoxOptions.None);
330 | }
331 | public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon)
332 | {
333 | return ShowCore(null, messageBoxText, caption, button, icon, MessageBoxResult.None, MessageBoxOptions.None);
334 | }
335 | public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult)
336 | {
337 | return ShowCore(null, messageBoxText, caption, button, icon, defaultResult, MessageBoxOptions.None);
338 | }
339 | public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)
340 | {
341 | return ShowCore(null, messageBoxText, caption, button, icon, defaultResult, options);
342 | }
343 | public static MessageBoxResult Show(IPopupItemContainer owner, string messageBoxText)
344 | {
345 | return ShowCore(owner, messageBoxText, null, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None, MessageBoxOptions.None);
346 | }
347 | public static MessageBoxResult Show(IPopupItemContainer owner, string messageBoxText, string caption)
348 | {
349 | return ShowCore(owner, messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.None, MessageBoxOptions.None);
350 | }
351 | public static MessageBoxResult Show(IPopupItemContainer owner, string messageBoxText, string caption, MessageBoxButton button)
352 | {
353 | return ShowCore(owner, messageBoxText, caption, button, MessageBoxImage.None, MessageBoxResult.None, MessageBoxOptions.None);
354 | }
355 | public static MessageBoxResult Show(IPopupItemContainer owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon)
356 | {
357 | return ShowCore(owner, messageBoxText, caption, button, icon, MessageBoxResult.None, MessageBoxOptions.None);
358 | }
359 | public static MessageBoxResult Show(IPopupItemContainer owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult)
360 | {
361 | return ShowCore(owner, messageBoxText, caption, button, icon, defaultResult, MessageBoxOptions.None);
362 | }
363 | public static MessageBoxResult Show(IPopupItemContainer owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)
364 | {
365 | return ShowCore(owner, messageBoxText, caption, button, icon, defaultResult, options);
366 | }
367 |
368 | private static MessageBoxResult ShowCore(IPopupItemContainer owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)
369 | {
370 | return Application.Current.Dispatcher.Invoke(() =>
371 | {
372 | if (owner == null)
373 | {
374 | owner = ViewManager.Instance.ActiveContainer;
375 | }
376 |
377 | MessageDialogBox messageDialogBox = new MessageDialogBox
378 | {
379 | MessageText = messageBoxText,
380 | Caption = caption,
381 | MessageBoxButton = button,
382 | MessageBoxImage = icon,
383 | DefaultResult = defaultResult,
384 | MessageBoxOptions = options
385 | };
386 | messageDialogBox._owner = owner;
387 |
388 | var modalresult = owner.ShowModal(messageDialogBox);
389 | if (modalresult == null)
390 | {
391 | return messageDialogBox.ConverterDefaultResult();
392 | }
393 | return (MessageBoxResult)modalresult.Result;
394 |
395 | }, DispatcherPriority.Send);
396 | }
397 | }
398 | }
399 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/System/Windows/ProcessDialogBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using System.Windows.Data;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Navigation;
13 | using System.Windows.Shapes;
14 | using System.Windows.Threading;
15 | using Unicorn.ViewManager;
16 |
17 | namespace System.Windows
18 | {
19 | [Flags]
20 | public enum ProcessBoxButton
21 | {
22 | None = 0x0,
23 | Cancel = 0x1,
24 | PauseContinue = 0x2,
25 | Stop = 0x4
26 | }
27 |
28 | public enum ProcessBoxImage
29 | {
30 | None
31 | }
32 |
33 |
34 | [TemplatePart(Name = PART_CANCELBUTTON, Type = typeof(Button))]
35 | [TemplatePart(Name = PART_PAUSEBUTTON, Type = typeof(Button))]
36 | [TemplatePart(Name = PART_CONTINUEBUTTON, Type = typeof(Button))]
37 | [TemplatePart(Name = PART_STOPBUTTON, Type = typeof(Button))]
38 | public sealed class ProcessDialogBox : Dialog, IDisposable
39 | {
40 | private const string PART_CANCELBUTTON = "PART_CANCELBUTTON";
41 | private const string PART_PAUSEBUTTON = "PART_PAUSEBUTTON";
42 | private const string PART_CONTINUEBUTTON = "PART_CONTINUEBUTTON";
43 | private const string PART_STOPBUTTON = "PART_STOPBUTTON";
44 |
45 | static ProcessDialogBox()
46 | {
47 | DefaultStyleKeyProperty.OverrideMetadata(typeof(ProcessDialogBox), new FrameworkPropertyMetadata(typeof(ProcessDialogBox)));
48 | }
49 |
50 | public bool IsIndeterminate
51 | {
52 | get
53 | {
54 | return (bool)GetValue(IsIndeterminateProperty);
55 | }
56 | private set
57 | {
58 | SetValue(IsIndeterminateProperty, value);
59 | }
60 | }
61 | public static readonly DependencyProperty IsIndeterminateProperty = DependencyProperty.Register("IsIndeterminate", typeof(bool), typeof(ProcessDialogBox), new PropertyMetadata(true));
62 |
63 | public string Caption
64 | {
65 | get
66 | {
67 | return this.Dispatcher.Invoke(() =>
68 | {
69 | return (string)GetValue(CaptionProperty);
70 | });
71 | }
72 | set
73 | {
74 | this.Dispatcher.Invoke(() =>
75 | {
76 | SetValue(CaptionProperty, value);
77 | });
78 | }
79 | }
80 | public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(string), typeof(ProcessDialogBox), new PropertyMetadata(string.Empty));
81 |
82 | public string MessageText
83 | {
84 | get
85 | {
86 | return this.Dispatcher.Invoke(() =>
87 | {
88 | return (string)GetValue(MessageTextProperty);
89 | });
90 | }
91 | set
92 | {
93 | this.Dispatcher.Invoke(() =>
94 | {
95 | SetValue(MessageTextProperty, value);
96 | });
97 | }
98 | }
99 | public static readonly DependencyProperty MessageTextProperty = DependencyProperty.Register("MessageText", typeof(string), typeof(ProcessDialogBox), new PropertyMetadata(string.Empty));
100 |
101 |
102 | public ProcessBoxButton ProcessBoxButton
103 | {
104 | get
105 | {
106 | return (ProcessBoxButton)GetValue(ProcessBoxButtonProperty);
107 | }
108 | private set
109 | {
110 | this.ThrowIfFreeze();
111 | SetValue(ProcessBoxButtonProperty, value);
112 | }
113 | }
114 | public static readonly DependencyProperty ProcessBoxButtonProperty = DependencyProperty.Register("ProcessBoxButton", typeof(ProcessBoxButton), typeof(ProcessDialogBox), new PropertyMetadata(ProcessBoxButton.None, ProcessBoxButtonChangedCallBack));
115 |
116 | private static void ProcessBoxButtonChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
117 | {
118 | ((ProcessDialogBox)d).RefrehButtonVisibility();
119 | }
120 |
121 | public ProcessBoxImage ProcessBoxImage
122 | {
123 | get
124 | {
125 | return (ProcessBoxImage)GetValue(ProcessBoxImageProperty);
126 | }
127 | private set
128 | {
129 | SetValue(ProcessBoxImageProperty, value);
130 | }
131 | }
132 | public static readonly DependencyProperty ProcessBoxImageProperty = DependencyProperty.Register("ProcessBoxImage", typeof(ProcessBoxImage), typeof(ProcessDialogBox), new PropertyMetadata(ProcessBoxImage.None));
133 |
134 | public double ProcessValue
135 | {
136 | get
137 | {
138 | return this.Dispatcher.Invoke(() =>
139 | {
140 | return (double)GetValue(ProcessValueProperty);
141 | });
142 | }
143 | set
144 | {
145 | this.Dispatcher.Invoke(() =>
146 | {
147 | SetValue(ProcessValueProperty, value);
148 | });
149 | }
150 | }
151 | public static readonly DependencyProperty ProcessValueProperty = DependencyProperty.Register("ProcessValue", typeof(double), typeof(ProcessDialogBox), new PropertyMetadata(0d));
152 |
153 |
154 | public double MaxProcess
155 | {
156 | get
157 | {
158 | return this.Dispatcher.Invoke(() =>
159 | {
160 | return (double)GetValue(MaxProcessProperty);
161 | });
162 | }
163 | set
164 | {
165 | this.Dispatcher.Invoke(() =>
166 | {
167 | SetValue(MaxProcessProperty, value);
168 | });
169 | }
170 | }
171 | public static readonly DependencyProperty MaxProcessProperty = DependencyProperty.Register("MaxProcess", typeof(double), typeof(ProcessDialogBox), new PropertyMetadata(100d));
172 |
173 |
174 | public void ReportProcess(double maxprocess, double processvalue)
175 | {
176 | this.ProcessValue = processvalue;
177 | this.MaxProcess = maxprocess;
178 | }
179 |
180 | private ProcessDialogBox()
181 | {
182 |
183 | }
184 |
185 | public void ThrowIfFreeze()
186 | {
187 | if (this._isFreezed)
188 | {
189 | throw new Exception("当前不可修改");
190 | }
191 | }
192 |
193 | private enum _ProcessStatus
194 | {
195 | NotStarted,
196 | Canceled,
197 | Running,
198 | Paused,
199 | Stoped
200 | }
201 | private _ProcessStatus _processStatus = _ProcessStatus.NotStarted;
202 | private Button _pauseBt = null,
203 | _continueBt = null,
204 | _stopBt = null,
205 | _cancelBt = null;
206 | private bool _isTemplateApply = false;
207 | private bool _isFreezed = false;
208 | private IPopupItemContainer _owner = null;
209 | public override void OnApplyTemplate()
210 | {
211 | base.OnApplyTemplate();
212 |
213 | _pauseBt = this.GetTemplateChild(PART_PAUSEBUTTON) as Button;
214 | _continueBt = this.GetTemplateChild(PART_CONTINUEBUTTON) as Button;
215 | _stopBt = this.GetTemplateChild(PART_STOPBUTTON) as Button;
216 | _cancelBt = this.GetTemplateChild(PART_CANCELBUTTON) as Button;
217 |
218 | if (this._pauseBt == null
219 | || this._continueBt == null
220 | || this._stopBt == null
221 | || this._cancelBt == null)
222 | {
223 | throw new Exception($"模板缺少必须元素{PART_PAUSEBUTTON}、{PART_CONTINUEBUTTON}、{PART_STOPBUTTON}、{PART_CANCELBUTTON}一个或多个");
224 | }
225 |
226 | this._isTemplateApply = true;
227 |
228 | this.RefrehButtonVisibility();
229 |
230 | this._pauseBt.Click += (sender, e) =>
231 | {
232 | if (this.PauseAction == null)
233 | {
234 | return;
235 | }
236 |
237 | try
238 | {
239 | this.PauseAction();
240 | }
241 | finally
242 | {
243 | this._pauseBt.Visibility = Visibility.Collapsed;
244 | this._pauseBt.IsEnabled = false;
245 |
246 | this._continueBt.Visibility = Visibility.Visible;
247 | this._continueBt.IsEnabled = true;
248 |
249 | this._processStatus = _ProcessStatus.Paused;
250 | }
251 | };
252 |
253 | this._continueBt.Click += (sender, e) =>
254 | {
255 | if (this.ContinueAction == null)
256 | {
257 | return;
258 | }
259 |
260 | try
261 | {
262 | this.ContinueAction();
263 | }
264 | finally
265 | {
266 | this._pauseBt.Visibility = Visibility.Visible;
267 | this._pauseBt.IsEnabled = true;
268 |
269 | this._continueBt.Visibility = Visibility.Collapsed;
270 | this._continueBt.IsEnabled = false;
271 |
272 | this._processStatus = _ProcessStatus.Running;
273 | }
274 | };
275 |
276 | this._stopBt.Click += (sender, e) =>
277 | {
278 | if (this.StopAction == null)
279 | {
280 | return;
281 | }
282 |
283 | try
284 | {
285 | this.StopAction();
286 | }
287 | finally
288 | {
289 | this._processStatus = _ProcessStatus.Stoped;
290 | this.Dispose();
291 | }
292 | };
293 |
294 | this._cancelBt.Click += (sender, e) =>
295 | {
296 | if (this.CancelAction == null)
297 | {
298 | return;
299 | }
300 |
301 | try
302 | {
303 | this.CancelAction();
304 | }
305 | finally
306 | {
307 | this._processStatus = _ProcessStatus.Canceled;
308 | this.Dispose();
309 | }
310 | };
311 | }
312 |
313 | private static bool IsFlagSet(ProcessBoxButton flag, ProcessBoxButton flags)
314 | {
315 | return (uint)(flags & flag) > 0U;
316 | }
317 |
318 | private void RefrehButtonVisibility()
319 | {
320 | if (!this._isTemplateApply)
321 | {
322 | return;
323 | }
324 |
325 | this._pauseBt.Visibility = Visibility.Collapsed;
326 | this._pauseBt.IsEnabled = false;
327 |
328 | this._continueBt.Visibility = Visibility.Collapsed;
329 | this._continueBt.IsEnabled = false;
330 |
331 | this._stopBt.Visibility = Visibility.Collapsed;
332 | this._stopBt.IsEnabled = false;
333 |
334 | this._cancelBt.Visibility = Visibility.Collapsed;
335 | this._cancelBt.IsEnabled = false;
336 |
337 | if (this.ProcessBoxButton != ProcessBoxButton.None)
338 | {
339 | if (IsFlagSet(ProcessBoxButton.Cancel, this.ProcessBoxButton))
340 | {
341 | this._cancelBt.Visibility = Visibility.Visible;
342 | this._cancelBt.IsEnabled = true;
343 | }
344 |
345 | if (IsFlagSet(ProcessBoxButton.PauseContinue, this.ProcessBoxButton))
346 | {
347 | this._pauseBt.Visibility = Visibility.Visible;
348 | this._pauseBt.IsEnabled = true;
349 | }
350 |
351 | if (IsFlagSet(ProcessBoxButton.Stop, this.ProcessBoxButton))
352 | {
353 | this._stopBt.Visibility = Visibility.Visible;
354 | this._stopBt.IsEnabled = true;
355 | }
356 | }
357 |
358 | this._isFreezed = true;
359 | }
360 |
361 | public Action CancelAction
362 | {
363 | get; set;
364 | }
365 |
366 | public Action PauseAction
367 | {
368 | get; set;
369 | }
370 |
371 | public Action ContinueAction
372 | {
373 | get; set;
374 | }
375 |
376 | public Action StopAction
377 | {
378 | get; set;
379 | }
380 |
381 | public void Dispose()
382 | {
383 | Application.Current.Dispatcher.Invoke(() =>
384 | {
385 | this._isFreezed = false;
386 | this._owner.Close(this);
387 | }, DispatcherPriority.Send);
388 | }
389 |
390 | public static ProcessDialogBox Show(string text, string caption)
391 | {
392 | return ShowCore(null, text, caption, true, ProcessBoxButton.None, ProcessBoxImage.None);
393 | }
394 | public static ProcessDialogBox Show(string text, string caption, bool isindeterminate)
395 | {
396 | return ShowCore(null, text, caption, isindeterminate, ProcessBoxButton.None, ProcessBoxImage.None);
397 | }
398 | public static ProcessDialogBox Show(string text, string caption, bool isindeterminate, ProcessBoxButton processBoxButton)
399 | {
400 | return ShowCore(null, text, caption, isindeterminate, processBoxButton, ProcessBoxImage.None);
401 | }
402 | public static ProcessDialogBox Show(string text, string caption, bool isindeterminate, ProcessBoxButton processBoxButton, ProcessBoxImage processBoxImage)
403 | {
404 | return ShowCore(null, text, caption, isindeterminate, processBoxButton, processBoxImage);
405 | }
406 |
407 | public static ProcessDialogBox Show(IPopupItemContainer owner, string text, string caption)
408 | {
409 | return ShowCore(owner, text, caption, true, ProcessBoxButton.None, ProcessBoxImage.None);
410 | }
411 | public static ProcessDialogBox Show(IPopupItemContainer owner, string text, string caption, bool isindeterminate)
412 | {
413 | return ShowCore(owner, text, caption, isindeterminate, ProcessBoxButton.None, ProcessBoxImage.None);
414 | }
415 | public static ProcessDialogBox Show(IPopupItemContainer owner, string text, string caption, bool isindeterminate, ProcessBoxButton processBoxButton)
416 | {
417 | return ShowCore(owner, text, caption, isindeterminate, processBoxButton, ProcessBoxImage.None);
418 | }
419 | public static ProcessDialogBox Show(IPopupItemContainer owner, string text, string caption, bool isindeterminate, ProcessBoxButton processBoxButton, ProcessBoxImage processBoxImage)
420 | {
421 | return ShowCore(owner, text, caption, isindeterminate, processBoxButton, processBoxImage);
422 | }
423 |
424 | private static ProcessDialogBox ShowCore(IPopupItemContainer owner, string text, string caption, bool isindeterminate, ProcessBoxButton processBoxButton, ProcessBoxImage processBoxImage)
425 | {
426 | return Application.Current.Dispatcher.Invoke(() =>
427 | {
428 | if (owner == null)
429 | {
430 | owner = ViewManager.Instance.ActiveContainer;
431 | }
432 |
433 | ProcessDialogBox processDialogBox = new ProcessDialogBox
434 | {
435 | MessageText = text,
436 | Caption = caption,
437 | IsIndeterminate = isindeterminate,
438 | ProcessBoxButton = processBoxButton,
439 | ProcessBoxImage = processBoxImage
440 | };
441 |
442 | processDialogBox._owner = owner;
443 |
444 | processDialogBox._owner.Show(processDialogBox);
445 |
446 | return processDialogBox;
447 |
448 | }, DispatcherPriority.Send);
449 | }
450 | }
451 | }
452 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/DefaultPopupItemContainer.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
20 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/Dialog.xaml:
--------------------------------------------------------------------------------
1 |
5 |
31 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/DialogContainer.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/Flyout.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
32 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/FlyoutContainer.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
64 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/Generic.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/MessageDialogBox.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/PopupItemContainer.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
26 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/PopupStack.xaml:
--------------------------------------------------------------------------------
1 |
5 |
14 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/PopupStackControl.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
17 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/ProcessDialogBox.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/RichViewControl.xaml:
--------------------------------------------------------------------------------
1 |
6 |
53 |
54 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/RichViewItem.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
20 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Themes/RichViewWindow.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
33 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/Unicorn.ViewManager.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | true
6 | Debug;Release;Dev;Test
7 | AnyCPU;x86
8 | Mr.Zhang
9 | Unicorn
10 | 3.1.5
11 | WPF的一个强大的视图管理库,基于视图栈的形式管理WPF项目中的各种视图。
12 | https://github.com/MrZhangYuan/Unicorn.ViewManager
13 | https://github.com/MrZhangYuan/Unicorn.ViewManager.git
14 | Git
15 | WPF;C#;.NET;.NET Core;WPF View Manager
16 | 3.1.5.0
17 | true
18 | snupkg
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/ViewCommands.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Windows.Input;
5 | using System.Windows.Threading;
6 |
7 | namespace Unicorn.ViewManager
8 | {
9 | public static class ViewCommands
10 | {
11 | //static ViewCommands()
12 | //{
13 | // DispatcherTimer dt = new DispatcherTimer(DispatcherPriority.Input)
14 | // {
15 | // Interval = TimeSpan.FromMilliseconds(500)
16 | // };
17 | // dt.Tick += (sender, e) =>
18 | // {
19 | // CommandManager.InvalidateRequerySuggested();
20 | // };
21 | // dt.Start();
22 | //}
23 |
24 | private enum CommandId : byte
25 | {
26 | ShowPopupItem,
27 | ClosePopupItem,
28 |
29 | ShowView,
30 | CloseView,
31 | SwitchView,
32 |
33 | Last
34 | }
35 |
36 | private static RoutedUICommand[] _internalCommands = new RoutedUICommand[(int)CommandId.Last];
37 |
38 | public static RoutedUICommand ShowPopupItem
39 | {
40 | get
41 | {
42 | return _EnsureCommand(CommandId.ShowPopupItem);
43 | }
44 | }
45 |
46 | public static RoutedUICommand ClosePopupItem
47 | {
48 | get
49 | {
50 | return _EnsureCommand(CommandId.ClosePopupItem);
51 | }
52 | }
53 |
54 | public static RoutedUICommand ShowView
55 | {
56 | get
57 | {
58 | return _EnsureCommand(CommandId.ShowView);
59 | }
60 | }
61 |
62 | public static RoutedUICommand CloseView
63 | {
64 | get
65 | {
66 | return _EnsureCommand(CommandId.CloseView);
67 | }
68 | }
69 |
70 | public static RoutedUICommand SwitchView
71 | {
72 | get
73 | {
74 | return _EnsureCommand(CommandId.SwitchView);
75 | }
76 | }
77 |
78 | private static RoutedUICommand _EnsureCommand(CommandId idCommand)
79 | {
80 | lock (_internalCommands.SyncRoot)
81 | {
82 | if (_internalCommands[(int)idCommand] == null)
83 | {
84 | _internalCommands[(int)idCommand] = new RoutedUICommand(
85 | GetUIText(idCommand),
86 | GetCommandName(idCommand),
87 | typeof(ViewCommands)
88 | );
89 | }
90 | }
91 | return _internalCommands[(int)idCommand];
92 | }
93 |
94 | private static string GetUIText(CommandId commandId)
95 | {
96 | return commandId.ToString();
97 | }
98 |
99 | private static string GetCommandName(CommandId commandId)
100 | {
101 | return commandId.ToString();
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/ViewManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Input;
9 | using Unicorn.ViewManager.Preferences;
10 |
11 | namespace Unicorn.ViewManager
12 | {
13 | public class ViewManager
14 | {
15 | public static ViewManager Instance
16 | {
17 | get;
18 | private set;
19 | }
20 |
21 | static ViewManager()
22 | {
23 | Instance = new ViewManager();
24 | }
25 |
26 | private ViewManager()
27 | {
28 |
29 | }
30 |
31 |
32 | private RichViewControl _richViewControl = null;
33 | public RichViewControl MainRichView
34 | {
35 | get => _richViewControl ?? (_richViewControl = new RichViewControl());
36 | }
37 |
38 | public ViewPreferences ViewPreferences
39 | {
40 | get => ViewPreferences.Instance;
41 | }
42 |
43 | public ContentControl HostContentControl
44 | {
45 | get;
46 | private set;
47 | }
48 |
49 | public void InitializeRichView(ContentControl contentControl)
50 | {
51 | if (contentControl == null)
52 | throw new ArgumentNullException(nameof(contentControl));
53 |
54 | this.HostContentControl = contentControl;
55 | contentControl.Content = this.MainRichView;
56 | }
57 |
58 |
59 | public ModalResult ShowModal(PopupItem item)
60 | {
61 | return this.MainRichView.ShowModal(item);
62 | }
63 |
64 | public void Show(PopupItem item)
65 | {
66 | this.MainRichView.Show(item);
67 | }
68 |
69 | public void Close(PopupItem item)
70 | {
71 | this.MainRichView.Close(item);
72 | }
73 |
74 | public void ShowView(object item)
75 | {
76 | this.MainRichView.ShowView(item);
77 | }
78 |
79 | public void CloseView(object item)
80 | {
81 | this.MainRichView.CloseView(item);
82 | }
83 |
84 | public void SwitchView(object item)
85 | {
86 | this.MainRichView.SwitchView(item);
87 | }
88 |
89 | public bool Close()
90 | {
91 | return this.MainRichView.Close();
92 | }
93 |
94 |
95 | public IPopupItemContainer ActiveContainer
96 | {
97 | get
98 | {
99 | IPopupItemContainer activecontainer = null;
100 |
101 | UIElement element = Keyboard.FocusedElement as UIElement;
102 | if (element != null
103 | && Window.GetWindow(element) is Window topwindow
104 | && topwindow is IPopupItemContainer topcontainer)
105 | {
106 | activecontainer = topcontainer;
107 | }
108 |
109 | if (activecontainer == null)
110 | {
111 | foreach (Window window in Application.Current.Windows)
112 | {
113 | if (window.IsActive)
114 | {
115 | if (window is IPopupItemContainer container)
116 | {
117 | activecontainer = container;
118 | break;
119 | }
120 | }
121 | }
122 | }
123 |
124 | if (activecontainer == null)
125 | {
126 | if (Application.Current.MainWindow is IPopupItemContainer main)
127 | {
128 | activecontainer = main;
129 | }
130 | }
131 |
132 | if (activecontainer == null)
133 | {
134 | activecontainer = this.MainRichView;
135 | }
136 | return activecontainer;
137 | }
138 | }
139 |
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/Unicorn.ViewManager/ViewStackChangedEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Unicorn.ViewManager
5 | {
6 | public enum ViewStackAction
7 | {
8 | Add = 0,
9 | Remove = 1,
10 | Replace = 2,
11 | Move = 3,
12 | Reset = 4
13 | }
14 |
15 | public delegate void ViewStackChangedEventHandler(object sender, ViewStackChangedEventArgs e);
16 |
17 | public class ViewStackChangedEventArgs : EventArgs
18 | {
19 | public ViewStackAction ViewStackAction { get; }
20 | public IList NewItems { get; }
21 | public int NewStartingIndex { get; }
22 | public IList OldItems { get; }
23 | public int OldStartingIndex { get; }
24 |
25 | public ViewStackChangedEventArgs(ViewStackAction viewStackAction,
26 | IList newItems,
27 | int newStartingIndex,
28 | IList oldItems,
29 | int oldStartingIndex)
30 | {
31 | ViewStackAction = viewStackAction;
32 | NewItems = newItems;
33 | NewStartingIndex = newStartingIndex;
34 | OldItems = oldItems;
35 | OldStartingIndex = oldStartingIndex;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------