├── .gitignore
├── Demo
├── App.config
├── App.xaml
├── App.xaml.cs
├── Demo.csproj
├── MainWindow.xaml
├── MainWindow.xaml.cs
└── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── README.md
├── TimeLine.sln
└── VideoStateAxis
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── Themes
└── Generic.xaml
├── VideoStateAxis.csproj
└── VideoStateAxisControl.cs
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | .vs/
4 |
--------------------------------------------------------------------------------
/Demo/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Demo/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Demo/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 Demo
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Demo/Demo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DB545297-421D-48C7-B8D1-4344CA7AE080}
8 | WinExe
9 | Demo
10 | Demo
11 | v4.5.2
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | 4.0
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | MSBuild:Compile
56 | Designer
57 |
58 |
59 | MSBuild:Compile
60 | Designer
61 |
62 |
63 | App.xaml
64 | Code
65 |
66 |
67 | MainWindow.xaml
68 | Code
69 |
70 |
71 |
72 |
73 | Code
74 |
75 |
76 | True
77 | True
78 | Resources.resx
79 |
80 |
81 | True
82 | Settings.settings
83 | True
84 |
85 |
86 | ResXFileCodeGenerator
87 | Resources.Designer.cs
88 |
89 |
90 | SettingsSingleFileGenerator
91 | Settings.Designer.cs
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | {c5dc4e69-c26f-4e0d-ba9a-0950a4c15d69}
100 | VideoStateAxis
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/Demo/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Demo/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.ObjectModel;
3 | using System.Windows;
4 | using VideoStateAxis;
5 |
6 | namespace Demo
7 | {
8 | ///
9 | /// Interaction logic for MainWindow.xaml
10 | ///
11 | public partial class MainWindow : Window
12 | {
13 | public MainWindow()
14 | {
15 | InitializeComponent();
16 | ContentRendered += MainWindow_ContentRendered;
17 | }
18 |
19 | private void MainWindow_ContentRendered(object sender, EventArgs e)
20 | {
21 | var VideoSource = new ObservableCollection();
22 |
23 | for (int i = 0; i < 10; i++)
24 | {
25 | var item = new VideoStateItem() { CameraName=$"Demo {i.ToString("D2")}",CameraChecked=i%2==0};
26 | var charList = new char[1000];
27 | for (int j = 0; j < 1000; j++)
28 | {
29 | charList[j] = '1';
30 | }
31 | item.AxisHistoryTimeList = charList;
32 | VideoSource.Add(item);
33 | }
34 |
35 | PART_TimeLine.HisVideoSources = VideoSource;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Demo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("Demo")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("Demo")]
15 | [assembly: AssemblyCopyright("Copyright © 2020")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/Demo/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Demo.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Demo.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Demo/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/Demo/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Demo.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Demo/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TimeAxis Control WPF
2 | ---
3 | The WPF-like control of the Adobe AE timeline is completely based on the binding of dependent attributes, which is very extensible and can be modified by itself
4 |
5 | #### View视图代码:
6 | ```C {.line-numbers}
7 |
8 | ```
9 |
10 | #### 已有依赖属性说明:
11 | >**SerStateTime**
12 | * Type:System.DateTime
13 | * 说明:时间轴开始搜索时间
14 |
15 | >**SerEndTime**
16 | * Type:System.DateTime
17 | * 说明:时间轴结束搜索时间
18 |
19 | >**HistoryVideoSources**
20 | * Type:List\
21 | * 说明:时间轴时间
22 | * 包含属性:
23 |
24 | ```java {.line-numbers}
25 | public class VideoStateItem
26 | {
27 | ///
28 | /// 相机名称
29 | ///
30 | public string CameraName { get; set; }
31 |
32 | ///
33 | /// 相机是否选中
34 | ///
35 | public bool CameraChecked { get; set; }
36 |
37 | ///
38 | /// 相机历史视频视频时间集
39 | ///
40 | public char[] AxisHistoryTimeList { get; set; }
41 | }
42 | ```
43 |
44 | 
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/TimeLine.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30011.22
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VideoStateAxis", "VideoStateAxis\VideoStateAxis.csproj", "{C5DC4E69-C26F-4E0D-BA9A-0950A4C15D69}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo", "Demo\Demo.csproj", "{DB545297-421D-48C7-B8D1-4344CA7AE080}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {C5DC4E69-C26F-4E0D-BA9A-0950A4C15D69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {C5DC4E69-C26F-4E0D-BA9A-0950A4C15D69}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {C5DC4E69-C26F-4E0D-BA9A-0950A4C15D69}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {C5DC4E69-C26F-4E0D-BA9A-0950A4C15D69}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {DB545297-421D-48C7-B8D1-4344CA7AE080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {DB545297-421D-48C7-B8D1-4344CA7AE080}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {DB545297-421D-48C7-B8D1-4344CA7AE080}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {DB545297-421D-48C7-B8D1-4344CA7AE080}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {258197CE-3808-4CEB-AC0F-0EA1755D8F19}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/VideoStateAxis/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("VideoStateAxis")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("VideoStateAxis")]
15 | [assembly: AssemblyCopyright("Copyright © 2017")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | //将 ComVisible 设置为 false 将使此程序集中的类型
20 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请设置
25 | //.csproj 文件中的 CultureYouAreCodingWith
26 | //例如,如果您在源文件中使用的是美国英语,
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly:ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(未在页面中找到资源时使用,
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(未在页面中找到资源时使用,
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
52 | // 方法是按如下所示使用“*”: :
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/VideoStateAxis/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace VideoStateAxis.Properties {
12 |
13 |
14 | ///
15 | /// 强类型资源类,用于查找本地化字符串等。
16 | ///
17 | // 此类是由 StronglyTypedResourceBuilder
18 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
19 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
20 | // (以 /str 作为命令选项),或重新生成 VS 项目。
21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
24 | internal class Resources {
25 |
26 | private static global::System.Resources.ResourceManager resourceMan;
27 |
28 | private static global::System.Globalization.CultureInfo resourceCulture;
29 |
30 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
31 | internal Resources() {
32 | }
33 |
34 | ///
35 | /// 返回此类使用的缓存 ResourceManager 实例。
36 | ///
37 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
38 | internal static global::System.Resources.ResourceManager ResourceManager {
39 | get {
40 | if ((resourceMan == null)) {
41 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VideoStateAxis.Properties.Resources", typeof(Resources).Assembly);
42 | resourceMan = temp;
43 | }
44 | return resourceMan;
45 | }
46 | }
47 |
48 | ///
49 | /// 覆盖当前线程的 CurrentUICulture 属性
50 | /// 使用此强类型的资源类的资源查找。
51 | ///
52 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
53 | internal static global::System.Globalization.CultureInfo Culture {
54 | get {
55 | return resourceCulture;
56 | }
57 | set {
58 | resourceCulture = value;
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/VideoStateAxis/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/VideoStateAxis/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace VideoStateAxis.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/VideoStateAxis/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/VideoStateAxis/Themes/Generic.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
53 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
97 |
98 |
99 |
103 |
109 |
113 |
120 |
126 |
127 |
128 |
129 |
130 |
131 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
151 |
159 |
168 |
175 |
176 |
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 |
224 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
251 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
278 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
321 |
329 |
338 |
345 |
346 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
401 |
402 | M955.346899 811.30069 742.294548 406.649604c-11.56643-22.054295-30.487362-22.054295-42.052768 0l-96.1652 182.621271c-11.628852 22.113647-30.487362 22.113647-42.116213 0L394.764414 271.622304c-11.57257-22.110577-30.364565-22.110577-42.059931 0L68.677661 811.30069c-11.622712 22.053272 1.689479 40.008202 29.765931 40.008202l367.720989 0 233.713926 0 225.703485 0C953.655374 851.307869 966.912305 833.352939 955.346899 811.30069M591.184969 320.909847c46.027289 0 83.208097-33.1981 83.208097-74.108858s-37.180807-74.108858-83.208097-74.108858c-45.911656 0-83.148745 33.1981-83.148745 74.108858S545.273313 320.909847 591.184969 320.909847
403 |
404 |
405 |
431 |
432 |
433 |
459 |
460 |
461 |
468 |
469 |
470 |
471 |
472 |
527 |
528 |
529 |
530 |
531 |
540 |
541 |
542 |
543 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
583 |
584 |
602 |
603 |
608 |
609 |
610 |
611 |
612 |
621 |
622 |
623 |
631 |
632 |
633 |
641 |
642 |
643 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
726 |
736 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
774 |
784 |
796 |
797 |
798 |
799 |
800 |
909 |
910 |
911 |
912 |
913 |
914 |
987 |
988 |
989 |
990 |
991 |
992 |
1004 |
1005 |
1006 |
1007 |
1008 |
1131 |
1136 |
1137 |
1138 |
1139 |
1140 |
1150 |
1151 |
1162 |
1163 |
1168 |
1180 |
1181 |
1182 |
1183 |
1224 |
1225 |
1226 |
1263 |
1264 |
1265 |
1266 |
1267 |
1273 |
1274 |
1275 |
1279 |
1280 |
1284 |
1285 |
1289 |
1290 |
1291 |
1292 |
1293 |
1294 |
1295 |
1296 |
1297 |
1298 |
1299 |
1300 |
1301 |
1302 |
1303 |
1304 |
1305 |
1306 |
1307 |
--------------------------------------------------------------------------------
/VideoStateAxis/VideoStateAxis.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {C5DC4E69-C26F-4E0D-BA9A-0950A4C15D69}
8 | library
9 | VideoStateAxis
10 | VideoStateAxis
11 | v4.5.2
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | 4.0
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | MSBuild:Compile
52 | Designer
53 |
54 |
55 |
56 |
57 | Code
58 |
59 |
60 | True
61 | True
62 | Resources.resx
63 |
64 |
65 | True
66 | Settings.settings
67 | True
68 |
69 |
70 |
71 | ResXFileCodeGenerator
72 | Resources.Designer.cs
73 |
74 |
75 | SettingsSingleFileGenerator
76 | Settings.Designer.cs
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/VideoStateAxis/VideoStateAxisControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Text.RegularExpressions;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using System.Windows.Controls;
12 | using System.Windows.Controls.Primitives;
13 | using System.Windows.Data;
14 | using System.Windows.Documents;
15 | using System.Windows.Input;
16 | using System.Windows.Media;
17 | using System.Windows.Media.Imaging;
18 | using System.Windows.Navigation;
19 | using System.Windows.Shapes;
20 |
21 | namespace VideoStateAxis
22 | {
23 | #region TemplatePart 模板元素声明
24 |
25 | [TemplatePart(Name = Parid_axisCanvas)]
26 | [TemplatePart(Name = Parid_timePoint)]
27 | [TemplatePart(Name = Parid_currentTime)]
28 | [TemplatePart(Name = Parid_timePanel)]
29 | [TemplatePart(Name = Parid_timeLine)]
30 | [TemplatePart(Name = Parid_scrollViewer)]
31 | [TemplatePart(Name = Parid_videoHistoryPanel)]
32 | [TemplatePart(Name = Parid__axisCanvasTimeText)]
33 | [TemplatePart(Name = Parid_zoomSlider)]
34 | [TemplatePart(Name = Parid_clipCanvas)]
35 | [TemplatePart(Name = Parid_clipStartBorder)]
36 | [TemplatePart(Name = Parid_clipAreaBorder)]
37 | [TemplatePart(Name = Parid_clipEndBorder)]
38 | [TemplatePart(Name = Parid_clipStackPanel)]
39 | [TemplatePart(Name = Parid_clipOff)]
40 | [TemplatePart(Name = Parid_clipStateTimeTextBlock)]
41 | [TemplatePart(Name = Parid_clipEndTimeTextBlock)]
42 | [TemplatePart(Name = Parid_cameraListBox)]
43 | [TemplatePart(Name = Parid_downButtonListBox)]
44 |
45 | #endregion
46 | public class VideoStateAxisControl : Control
47 | {
48 | #region UIElement 模板元素
49 |
50 | private StackPanel _videoHistoryPanel; //历史时间轴容器
51 | private ScrollViewer _scrollViewer; //滚动视图
52 | private Canvas _axisCanvas; //时间刻度尺容器
53 | private Canvas _axisCanvasTimeText; //时间刻度时间文字容器
54 | private Slider _zoomSlider; //缩放时间轴滑块
55 |
56 | private TextBlock _currentTime; //进度指针时间
57 | private Canvas _timePanel; //进度容器
58 | private Canvas _timeLine; //进度指针容器
59 | private Grid _timePoint; //进度指针
60 |
61 | private Canvas _clipCanvas; //剪辑控制移动容器
62 | private Border _clipStartBorder; //剪辑左调解
63 | private Border _clipAreaBorder; //剪辑滑块
64 | private Border _clipEndBorder; //剪辑右调解
65 | private StackPanel _clipStackPanel; //剪辑滑块容器
66 | private CheckBox _clipOff; //是否开启剪辑控制
67 |
68 | private TextBlock _clipStateTimeTextBlock; //剪辑开始时间指示器
69 | private TextBlock _clipEndTimeTextBlock; //剪辑结束时间指示器
70 |
71 | private ListBox _cameraListBox; //相机列表
72 | private ListBox _downButtonListBox; //下载列表
73 | private ScrollViewer _cameraScrollViewer; //相机列表ScrollViewer
74 | private ScrollViewer _downScrollViewer; //下载列表ScrollViewer
75 |
76 | #endregion
77 |
78 | #region ConstString 模板元素名称,Geometry图像数据
79 |
80 | private const string Parid_axisCanvas = "Z_Parid_axisCanvas";
81 | private const string Parid__axisCanvasTimeText = "Z_Parid__axisCanvasTimeText";
82 | private const string Parid_zoomPanel = "Z_Parid_zoomPanel";
83 | private const string Parid_timePoint = "Z_Parid_timePoint";
84 | private const string Parid_currentTime = "Z_Parid_currentTime";
85 | private const string Parid_timePanel = "Z_Parid_timePanel";
86 | private const string Parid_timeLine = "Z_Parid_timeLine";
87 | private const string Parid_scrollViewer = "Z_Parid_scrollViewer";
88 | private const string Parid_videoHistoryPanel = "Z_videoHistoryPanel";
89 | private const string Parid_zoomSlider = "Z_Parid_zoomSlider";
90 | private const string Parid_clipCanvas = "Z_Parid_clipCanvas";
91 | private const string Parid_clipStartBorder = "Z_Parid_clipStartBorder";
92 | private const string Parid_clipAreaBorder = "Z_Parid_clipAreaBorder";
93 | private const string Parid_clipEndBorder = "Z_Parid_clipEndBorder";
94 | private const string Parid_clipStackPanel = "Z_Parid_clipStackPanel";
95 | private const string Parid_clipOff = "Z_Parid_clipOff";
96 | private const string Parid_clipStateTimeTextBlock = "Z_Parid_clipStateTimeTextBlock";
97 | private const string Parid_clipEndTimeTextBlock = "Z_Parid_clipEndTimeTextBlock";
98 | private const string Parid_cameraListBox = "Z_Parid_cameraListBox";
99 | private const string Parid_downButtonListBox = "Z_Parid_downButtonListBox";
100 |
101 | private const string GeometryDown = "M954.123536 509.086647 526.172791 932.999426c-8.074909 8.074909-20.185738 8.074909-28.260647 0L69.960375 509.086647c-12.110829-14.130835-4.427846-34.317597 14.130835-34.317597l215.994356 0L300.085566 107.149369c0-12.111852 10.093892-22.205745 22.204721-22.205745l379.50436 0c12.110829 0 22.204721 10.093892 22.204721 24.223704l0 365.601722 215.994356 0C958.159456 474.770074 966.234365 496.975818 954.123536 509.086647z";
102 | private const string GeometryFavorite = "M1024 378.88l-314.647273-37.236364L512 0 314.647273 341.643636 0 378.88l236.450909 266.24L191.767273 1024 512 872.261818 832.232727 1024l-44.683636-378.88L1024 378.88z";
103 | private const string GeometryOpen = "M512 68.191078c-245.204631 0-443.808922 198.60429-443.808922 443.808922s198.60429 443.808922 443.808922 443.808922 443.808922-198.60429 443.808922-443.808922S757.203608 68.191078 512 68.191078zM423.23842 711.713554 423.23842 312.285422l266.284739 199.713554L423.23842 711.713554z";
104 |
105 | #endregion
106 |
107 | #region DependencyProperty 依赖项属性
108 | public static readonly DependencyProperty HistoryVideoSourceProperty = DependencyProperty.Register(
109 | "HisVideoSources",
110 | typeof(ObservableCollection),
111 | typeof(VideoStateAxisControl),
112 | new PropertyMetadata(new ObservableCollection(), OnHistoryVideoSourcesChanged));
113 |
114 | public static readonly DependencyProperty StartTimeProperty = DependencyProperty.Register(
115 | "StartTime",
116 | typeof(DateTime),
117 | typeof(VideoStateAxisControl),
118 | new PropertyMetadata(OnTimeChanged));
119 |
120 | public static readonly DependencyProperty EndTimeProperty = DependencyProperty.Register(
121 | "EndTime",
122 | typeof(DateTime),
123 | typeof(VideoStateAxisControl),
124 | new PropertyMetadata(OnTimeChanged));
125 |
126 | public static readonly DependencyProperty AxisTimeProperty = DependencyProperty.Register(
127 | "AxisTime",
128 | typeof(DateTime),
129 | typeof(VideoStateAxisControl),
130 | new PropertyMetadata(OnAxisTimeChanged));
131 |
132 | public static readonly DependencyProperty ClipStartTimeProperty = DependencyProperty.Register(
133 | "ClipStartTime",
134 | typeof(DateTime),
135 | typeof(VideoStateAxisControl),
136 | new PropertyMetadata(OnClipTimeChanged));
137 |
138 | public static readonly DependencyProperty ClipEndTimeProperty = DependencyProperty.Register(
139 | "ClipEndTime",
140 | typeof(DateTime),
141 | typeof(VideoStateAxisControl),
142 | new PropertyMetadata(OnClipTimeChanged));
143 |
144 | public static readonly DependencyProperty ClipOffProperty = DependencyProperty.Register(
145 | "ClipOff",
146 | typeof(bool),
147 | typeof(VideoStateAxisControl),
148 | new PropertyMetadata(OnClipOffChanged));
149 |
150 | #endregion
151 |
152 | #region Property 属性关联字段
153 |
154 |
155 | ///
156 | /// 搜索历史视频开始时间
157 | ///
158 | public DateTime StartTime
159 | {
160 | get { return (DateTime)GetValue(StartTimeProperty); }
161 | set { SetValue(StartTimeProperty, value); }
162 | }
163 |
164 | ///
165 | /// 搜索历史视频结束时间
166 | ///
167 | public DateTime EndTime
168 | {
169 | get { return (DateTime)GetValue(EndTimeProperty); }
170 | set { SetValue(EndTimeProperty, value); }
171 | }
172 |
173 | ///
174 | /// 剪辑开启控制
175 | ///
176 | public bool ClipOff
177 | {
178 | get { return (bool)GetValue(ClipOffProperty); }
179 | set { SetValue(ClipOffProperty, value); }
180 | }
181 |
182 | ///
183 | /// 剪辑结束时间
184 | ///
185 | public DateTime ClipEndTime
186 | {
187 | get { return (DateTime)GetValue(ClipEndTimeProperty); }
188 | set { SetValue(ClipEndTimeProperty, value); }
189 | }
190 |
191 | ///
192 | /// 剪辑开始时间
193 | ///
194 | public DateTime ClipStartTime
195 | {
196 | get { return (DateTime)GetValue(ClipStartTimeProperty); }
197 | set { SetValue(ClipStartTimeProperty, value); }
198 | }
199 |
200 | ///
201 | /// 指针时间
202 | ///
203 | public DateTime AxisTime
204 | {
205 | get { return (DateTime)GetValue(AxisTimeProperty); }
206 | set { SetValue(AxisTimeProperty, value); }
207 | }
208 |
209 | ///
210 | /// 历史视频来源列表
211 | ///
212 | public ObservableCollection HisVideoSources
213 | {
214 | get { return (ObservableCollection)GetValue(HistoryVideoSourceProperty); }
215 | set { SetValue(HistoryVideoSourceProperty, value); }
216 | }
217 |
218 | ///
219 | /// 每小时占用时间轴的的宽度
220 | ///
221 | private double Dial_Cell_H
222 | {
223 | get { return _scrollViewer == null ? 0 : ((_scrollViewer.ActualWidth - 10) * Slider_Magnification) / 24; }
224 | }
225 |
226 | ///
227 | /// 每分钟占用时间轴的的宽度
228 | ///
229 | private double Dial_Cell_M
230 | {
231 | get { return Dial_Cell_H / 60; }
232 | }
233 |
234 | ///
235 | /// 每秒占用时间轴的的宽度
236 | ///
237 | private double Dial_Cell_S
238 | {
239 | get { return Dial_Cell_M / 60; }
240 | }
241 |
242 | ///
243 | /// 剪辑开始鼠标按下位置
244 | ///
245 | private double ClipStart_MouseDown_Offset = 0;
246 |
247 | ///
248 | /// 剪辑鼠标按下左坐标
249 | ///
250 | private double Start_MouseDown_ClipOffset = 0;
251 |
252 | ///
253 | /// 鼠标按下剪辑滑块宽度
254 | ///
255 | private double ClipStart_MouseDown_AreaWidth = 0;
256 |
257 | ///
258 | /// 时间轴缩放比例
259 | ///
260 | private double Slider_Magnification = 1;
261 |
262 | #endregion
263 |
264 | #region RouteEvent 路由事件
265 |
266 | public static readonly RoutedEvent AxisDownRoutedEvent = EventManager.RegisterRoutedEvent(
267 | "AxisDown",
268 | RoutingStrategy.Bubble,
269 | typeof(EventHandler),
270 | typeof(VideoStateAxisControl));
271 |
272 | public static readonly RoutedEvent DragTimeLineRoutedEvent = EventManager.RegisterRoutedEvent(
273 | "DragTimeLine",
274 | RoutingStrategy.Bubble,
275 | typeof(EventHandler),
276 | typeof(VideoStateAxisControl));
277 |
278 | ///
279 | /// 下载路由事件
280 | ///
281 | public event RoutedEventHandler AxisDown
282 | {
283 | add { this.AddHandler(AxisDownRoutedEvent, value); }
284 | remove { this.RemoveHandler(AxisDownRoutedEvent, value); }
285 | }
286 |
287 | ///
288 | /// 指针拖动事件
289 | ///
290 | public event RoutedEventHandler DragTimeLine
291 | {
292 | add { this.AddHandler(DragTimeLineRoutedEvent, value); }
293 | remove { this.RemoveHandler(DragTimeLineRoutedEvent, value); }
294 | }
295 |
296 | #endregion
297 |
298 | #region Method 方法
299 |
300 | ///
301 | /// 历史查询时间 - 改变
302 | ///
303 | ///
304 | ///
305 | private static void OnTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
306 | {
307 | VideoStateAxisControl AxisOb = d as VideoStateAxisControl;
308 | if (AxisOb != null)
309 | {
310 | AxisOb.InitializeAxis();
311 | }
312 | }
313 |
314 | ///
315 | /// 历史视频来源 - 改变
316 | ///
317 | ///
318 | ///
319 | private static void OnHistoryVideoSourcesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
320 | {
321 | VideoStateAxisControl AxisOb = d as VideoStateAxisControl;
322 | if (AxisOb.HisVideoSources != null && AxisOb.HisVideoSources.Count() > 0)
323 | {
324 | AxisOb.InitializeAxis();
325 | }
326 | AxisOb.HisVideoSources.CollectionChanged += (s, o) =>
327 | {
328 | AxisOb.AddHisPie();
329 | AxisOb.InitiaListBox_ScrollChanged();
330 | };
331 | }
332 |
333 | ///
334 | /// 指针时间刷新指针位置
335 | ///
336 | ///
337 | ///
338 | private static void OnAxisTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
339 | {
340 | VideoStateAxisControl AxisOb = d as VideoStateAxisControl;
341 | if (AxisOb != null && e.NewValue != e.OldValue)
342 | {
343 | AxisOb.RefreshTimeLineLeft((DateTime)e.NewValue);
344 | }
345 | }
346 |
347 | ///
348 | /// 剪辑时间变化,刷新剪辑控制条
349 | ///
350 | ///
351 | ///
352 | private static void OnClipTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
353 | {
354 | VideoStateAxisControl AxisOb = d as VideoStateAxisControl;
355 | if (AxisOb != null && e.NewValue != e.OldValue)
356 | {
357 | if (e.Property.Name == nameof(AxisOb.ClipStartTime))
358 | {
359 | AxisOb.ClipStartTimeChanged((DateTime)e.NewValue);
360 | }
361 | if (e.Property.Name == nameof(AxisOb.ClipEndTime))
362 | {
363 | AxisOb.ClipEndTimeChanged((DateTime)e.NewValue);
364 | }
365 | }
366 | }
367 |
368 | ///
369 | /// 剪辑开启控制源改变事件
370 | ///
371 | ///
372 | ///
373 | private static void OnClipOffChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
374 | {
375 | VideoStateAxisControl AxisOb = d as VideoStateAxisControl;
376 | if (AxisOb != null && e.NewValue != e.OldValue)
377 | {
378 | AxisOb.ClipOff = (bool)e.NewValue;
379 | AxisOb._clipOff.IsChecked = ((bool)e.NewValue) ? true : false;
380 | }
381 | }
382 |
383 | ///
384 | /// 构造函数初始化一些属性和样式
385 | ///
386 | public VideoStateAxisControl()
387 | {
388 | Loaded += delegate
389 | {
390 | InitializeAxis();
391 | SizeChanged += delegate
392 | {
393 | InitializeAxis();
394 | };
395 | };
396 | }
397 |
398 | ///
399 | /// 刷新指针位置
400 | ///
401 | ///
402 | private void RefreshTimeLineLeft(DateTime dt)
403 | {
404 | TimeSpan ts = dt - StartTime.Date;
405 | if (_timeLine != null)
406 | {
407 | Canvas.SetLeft(_timeLine,
408 | Dial_Cell_H * (ts.Days == 1 ? 23 : dt.Hour) +
409 | Dial_Cell_M * (ts.Days == 1 ? 59 : dt.Minute) +
410 | Dial_Cell_S * (ts.Days == 1 ? 59 : dt.Second));
411 | _currentTime.Text = dt.ToString(" [ yyyy-MM-dd ] HH:mm:ss");
412 | }
413 | }
414 |
415 | ///
416 | /// 剪辑鼠标弹起
417 | ///
418 | ///
419 | ///
420 | private void Clip_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
421 | {
422 | Border bor = sender as Border;
423 | if (bor != null)
424 | {
425 | bor.ReleaseMouseCapture();
426 | }
427 | }
428 |
429 | ///
430 | /// 剪辑鼠标点击
431 | ///
432 | ///
433 | ///
434 | private void Clip_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
435 | {
436 | Border bor = sender as Border;
437 | if (bor != null)
438 | {
439 | bor.CaptureMouse();
440 | ClipStart_MouseDown_Offset = e.GetPosition(_clipCanvas).X;
441 | Start_MouseDown_ClipOffset = _clipStackPanel.Margin.Left;
442 | ClipStart_MouseDown_AreaWidth = _clipStackPanel.Margin.Left + _clipStackPanel.ActualWidth;
443 | }
444 | }
445 |
446 | ///
447 | /// 剪辑鼠标移动,释放鼠标捕获
448 | ///
449 | ///
450 | ///
451 | private void Clip_MouseMove(object sender, MouseEventArgs e)
452 | {
453 | Border bor = sender as Border;
454 | if (bor != null && e.LeftButton == MouseButtonState.Pressed)
455 | {
456 | switch (bor.Name)
457 | {
458 | case Parid_clipStartBorder:
459 | ClipStart(e.GetPosition(_clipCanvas));
460 | break;
461 |
462 | case Parid_clipEndBorder:
463 | ClipEnd(e.GetPosition(_clipCanvas));
464 | break;
465 |
466 | case Parid_clipAreaBorder:
467 | MoveClipArea(e.GetPosition(_clipCanvas));
468 | break;
469 | }
470 | MathClipTime();
471 | }
472 | }
473 |
474 | ///
475 | /// 剪辑开始滑块增量
476 | ///
477 | ///
478 | private void ClipStart(Point pt)
479 | {
480 | if (pt.X >= 0)
481 | {
482 | double clipWidth = ClipStart_MouseDown_AreaWidth - (Start_MouseDown_ClipOffset + (pt.X - ClipStart_MouseDown_Offset) < 0 ? 0 :
483 | Start_MouseDown_ClipOffset + (pt.X - ClipStart_MouseDown_Offset) > _clipCanvas.ActualWidth - _clipAreaBorder.Width ?
484 | _axisCanvas.ActualWidth - _clipAreaBorder.Width :
485 | Start_MouseDown_ClipOffset + (pt.X - ClipStart_MouseDown_Offset)) - 10;
486 | _clipAreaBorder.Width = clipWidth <= 0 ? 0 : clipWidth;
487 | if (clipWidth >= 0)
488 | {
489 | MoveClipArea(pt);
490 | }
491 | }
492 | }
493 |
494 | ///
495 | /// 剪辑结束滑块增量
496 | ///
497 | private void ClipEnd(Point pt)
498 | {
499 | double clipWidth = pt.X - _clipStackPanel.Margin.Left;
500 | _clipAreaBorder.Width = clipWidth <= 0 ? 0 :
501 | clipWidth > _axisCanvas.ActualWidth - _clipStackPanel.Margin.Left ?
502 | _axisCanvas.ActualWidth - _clipStackPanel.Margin.Left : clipWidth;
503 | }
504 |
505 | ///
506 | /// 剪辑滚动滑块
507 | ///
508 | ///
509 | private void MoveClipArea(Point pt)
510 | {
511 | double clipLeft = Start_MouseDown_ClipOffset + (pt.X - ClipStart_MouseDown_Offset) < 0 ? 0 :
512 | Start_MouseDown_ClipOffset + (pt.X - ClipStart_MouseDown_Offset) > _clipCanvas.ActualWidth - _clipAreaBorder.Width ?
513 | _axisCanvas.ActualWidth - _clipAreaBorder.Width :
514 | Start_MouseDown_ClipOffset + (pt.X - ClipStart_MouseDown_Offset);
515 | _clipStackPanel.Margin = new Thickness(clipLeft, 0, 0, 0);
516 | }
517 |
518 | ///
519 | /// 时间缩放滑块事件
520 | ///
521 | ///
522 | ///
523 | private void _zoomSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
524 | {
525 | Slider_Magnification = Math.Round(e.NewValue, 2);
526 | InitializeAxis();
527 | }
528 |
529 | ///
530 | /// 滚动重置时间刻度位置
531 | ///
532 | ///
533 | ///
534 | private void scrollViewer_Changed(object sender, ScrollChangedEventArgs e)
535 | {
536 | _timeLine.Margin = new Thickness(0, _scrollViewer.VerticalOffset, 0, 0);
537 | _axisCanvasTimeText.Margin = new Thickness(0, _scrollViewer.VerticalOffset, 0, 0);
538 | _axisCanvas.Margin = new Thickness(0, _scrollViewer.VerticalOffset, 0, 0);
539 | _clipCanvas.Margin = new Thickness(0, _scrollViewer.VerticalOffset, 0, 0);
540 |
541 |
542 | if (_cameraScrollViewer != null)
543 | {
544 | double offset = _scrollViewer.VerticalOffset / _scrollViewer.ScrollableHeight * _cameraScrollViewer.ScrollableHeight;
545 | _cameraScrollViewer.ScrollToVerticalOffset(double.IsNaN(offset) ? 0 : offset);
546 | }
547 | if (_downScrollViewer != null)
548 | {
549 | double offset = _scrollViewer.VerticalOffset / _scrollViewer.ScrollableHeight * _downScrollViewer.ScrollableHeight;
550 | _downScrollViewer.ScrollToVerticalOffset(double.IsNaN(offset) ? 0 : offset);
551 | }
552 | }
553 |
554 | ///
555 | /// 相机列表ListBox的ScrollerViewerChanged事件
556 | ///
557 | ///
558 | ///
559 | private void _cameraScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
560 | {
561 | if (_scrollViewer != null)
562 | {
563 | double offset = _cameraScrollViewer.VerticalOffset / _cameraScrollViewer.ScrollableHeight * _scrollViewer.ScrollableHeight;
564 | _scrollViewer.ScrollToVerticalOffset(double.IsNaN(offset) ? 0 : offset);
565 | }
566 | if (_downScrollViewer != null)
567 | {
568 | _downScrollViewer.ScrollToVerticalOffset(_cameraScrollViewer.VerticalOffset);
569 | }
570 | }
571 |
572 | ///
573 | /// 下载列表ListBox的ScrollerViewerChanged事件
574 | ///
575 | ///
576 | ///
577 | private void _downScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
578 | {
579 | if (_scrollViewer != null)
580 | {
581 | double offset = _downScrollViewer.VerticalOffset / _downScrollViewer.ScrollableHeight * _scrollViewer.ScrollableHeight;
582 | _scrollViewer.ScrollToVerticalOffset(double.IsNaN(offset) ? 0 : offset);
583 | }
584 | if (_cameraScrollViewer != null)
585 | {
586 | _cameraScrollViewer.ScrollToVerticalOffset(_downScrollViewer.VerticalOffset);
587 | }
588 | }
589 |
590 | ///
591 | /// 指针移动
592 | ///
593 | ///
594 | ///
595 | private void timePoint_MouseMove(object sender, MouseEventArgs s)
596 | {
597 | if (Mouse.LeftButton == MouseButtonState.Pressed)
598 | {
599 | double delta = s.GetPosition(_timePanel).X;
600 | double timePointMaxLeft = _timePanel.ActualWidth - _timePoint.ActualWidth;
601 | Canvas.SetLeft(_timeLine, delta = delta < 0 ? 0 : (delta > timePointMaxLeft ? timePointMaxLeft : delta));
602 | TimeLine_Resver(delta);
603 | }
604 | }
605 |
606 | ///
607 | /// 刷新时间指示器坐标位置
608 | ///
609 | /// 鼠标位于Canvas坐标X
610 | private void TimeLine_Resver(double delta)
611 | {
612 | double timePointMaxLeft = _timePanel.ActualWidth - _timePoint.ActualWidth;
613 | double currentTimeMaxLeft = _timePanel.ActualWidth - _currentTime.ActualWidth;
614 | _currentTime.Text = (AxisTime = XToDateTime(delta < 0 ? 0 : (delta > timePointMaxLeft ? timePointMaxLeft : delta))).ToString(" [ yyyy-MM-dd ] HH:mm:ss");
615 | _currentTime.Margin = delta < currentTimeMaxLeft ?
616 | new Thickness(delta < 0 ? 10 : delta + 10, 2, 0, 0) :
617 | new Thickness(delta > timePointMaxLeft ? timePointMaxLeft - _currentTime.ActualWidth : delta - _currentTime.ActualWidth, 2, 0, 0);
618 | }
619 |
620 | ///
621 | /// 剪辑控制开启Checked事件
622 | ///
623 | ///
624 | ///
625 | private void Clip_UnChecked_Checked(object sender, RoutedEventArgs e)
626 | {
627 | CheckBox check = sender as CheckBox;
628 | if (check != null)
629 | {
630 | ClipOff = check.IsChecked == null || check.IsChecked == false ? false : true;
631 | }
632 | }
633 |
634 | ///
635 | /// 指针按下
636 | ///
637 | ///
638 | ///
639 | private void timePoint_MouseLeftButtonDown(object sender, MouseButtonEventArgs s)
640 | {
641 | _currentTime.Visibility = Visibility.Visible;
642 | _timePoint.CaptureMouse();
643 | }
644 |
645 | ///
646 | /// 发布指针拖动路由事件
647 | ///
648 | private void SendDragTimeLineRoutedEvent()
649 | {
650 | VideoStateAxisRoutedEventArgs args = new VideoStateAxisRoutedEventArgs(DragTimeLineRoutedEvent, this)
651 | {
652 | TimeLine = AxisTime
653 | };
654 | this.RaiseEvent(args);
655 | }
656 |
657 | ///
658 | /// 指针弹起
659 | ///
660 | ///
661 | ///
662 | private void timePoint_MouseLeftButtonUp(object sender, MouseButtonEventArgs s)
663 | {
664 | _currentTime.Visibility = Visibility.Collapsed;
665 | _timePoint.ReleaseMouseCapture();
666 | SendDragTimeLineRoutedEvent();
667 | }
668 |
669 | ///
670 | /// 计算指针拖动的显示时间
671 | ///
672 | /// 指针在Canvas容器中的Left坐标值
673 | private DateTime XToDateTime(double point_x)
674 | {
675 | DateTime dt = StartTime.Date;
676 | double time;
677 | int H, M, S;
678 | time = point_x / Dial_Cell_H;
679 | H = (int)(time);
680 | time = (time - H) * 60;
681 | M = (int)(time);
682 | S = (int)((time - M) * 60);
683 | return dt.AddHours(H).AddMinutes(M).AddSeconds(S);
684 | }
685 |
686 | ///
687 | /// 初始化
688 | ///
689 | private void InitializeAxis()
690 | {
691 | AddTimeTextBlock();
692 | AddTimeLine();
693 | AddHisPie();
694 | ClipStartTimeChanged(ClipStartTime);
695 | ClipEndTimeChanged(ClipEndTime);
696 | InitiaClipTime();
697 | InitiaListBox_ScrollChanged();
698 | InitializationNewtTimeLine();
699 | }
700 |
701 | ///
702 | /// 初始化剪辑时间
703 | ///
704 | private void InitiaClipTime()
705 | {
706 | ClipStartTime = ClipStartTime.Year == DateTime.Parse("0001/1/1 0:00:00").Year ? StartTime.Date : ClipStartTime;
707 | ClipEndTime = ClipEndTime.Year == DateTime.Parse("0001/1/1 0:00:00").Year ? StartTime.Date.AddDays(1) : ClipEndTime;
708 | }
709 |
710 | ///
711 | /// 初始化相机列表ListBox的ScrollerViewerChanged事件
712 | ///
713 | private void InitiaListBox_ScrollChanged()
714 | {
715 | if (_cameraListBox != null)
716 | {
717 | Decorator carmeraborder = VisualTreeHelper.GetChild(_cameraListBox, 0) as Decorator;
718 | if (carmeraborder != null)
719 | {
720 | _cameraScrollViewer = carmeraborder.Child as ScrollViewer;
721 | if (_cameraScrollViewer != null)
722 | {
723 | _cameraScrollViewer.ScrollChanged += _cameraScrollViewer_ScrollChanged;
724 | }
725 | }
726 | }
727 |
728 | if (_downButtonListBox != null)
729 | {
730 | Decorator downborder = VisualTreeHelper.GetChild(_downButtonListBox, 0) as Decorator;
731 | if (downborder != null)
732 | {
733 | _downScrollViewer = downborder.Child as ScrollViewer;
734 | if (_downScrollViewer != null)
735 | {
736 | _downScrollViewer.ScrollChanged += _downScrollViewer_ScrollChanged;
737 | }
738 | }
739 | }
740 | }
741 |
742 | ///
743 | /// 计算剪辑时间
744 | ///
745 | private void MathClipTime()
746 | {
747 | ClipStartTime = XToDateTime(_clipStackPanel.Margin.Left);
748 | ClipEndTime = XToDateTime(_clipStackPanel.Margin.Left + _clipAreaBorder.ActualWidth);
749 | }
750 |
751 | ///
752 | /// 重新计算剪辑时间为准的剪辑条左坐标
753 | ///
754 | private void ClipStartTimeChanged(DateTime dt)
755 | {
756 | TimeSpan ts = dt - StartTime.Date;
757 | if (ts.Days <= 1 && ts.Seconds >= 0 && _clipStackPanel != null)
758 | {
759 | double left = Dial_Cell_H * (ts.Days == 1 ? 23 : dt.Hour) + Dial_Cell_M * (ts.Days == 1 ? 59 : dt.Minute) + Dial_Cell_S * (ts.Days == 1 ? 59 : dt.Second);
760 | _clipStackPanel.Margin = new Thickness(left, 0, 0, 0);
761 | }
762 | }
763 |
764 | ///
765 | /// 重新计算剪辑时间为准的剪辑条宽度
766 | ///
767 | ///
768 | private void ClipEndTimeChanged(DateTime dt)
769 | {
770 | TimeSpan ts = dt - ClipStartTime;
771 | if (ts.Days <= 1 && ts.Seconds >= 0 && _clipAreaBorder != null)
772 | {
773 | double width = Dial_Cell_H * (ts.Days == 1 ? 23 : ts.Hours) + Dial_Cell_M * (ts.Days == 1 ? 59 : ts.Minutes) + Dial_Cell_S * (ts.Days == 1 ? 59 : ts.Seconds);
774 | _clipAreaBorder.Width = width;
775 | }
776 | }
777 |
778 | ///
779 | /// 初始化指针位置
780 | ///
781 | private void InitializationNewtTimeLine()
782 | {
783 | if (_timeLine != null && !double.IsNaN(Canvas.GetLeft(_timeLine)))
784 | {
785 | RefreshTimeLineLeft(AxisTime);
786 | }
787 | }
788 |
789 | ///
790 | /// 初始化时间刻度文字
791 | ///
792 | /// 需要填充的时间文字数量
793 | private void AddTimeTextBlock()
794 | {
795 | if (_axisCanvasTimeText != null)
796 | {
797 | _axisCanvasTimeText.Width = (_scrollViewer.ActualWidth - 10) * Slider_Magnification;
798 | _axisCanvasTimeText.Children.Clear();
799 | for (int i = 0; i < 24; i++)
800 | {
801 | _axisCanvasTimeText.Children.Add((
802 | new TextBlock()
803 | {
804 | Text = i.ToString().PadLeft(2, '0') + ":00",
805 | Margin = new Thickness(Dial_Cell_H * i, 2, 0, 0)
806 | }));
807 | }
808 | }
809 | }
810 |
811 | ///
812 | /// 初始化时间刻度
813 | ///
814 | /// 需要填充的时间刻度数量
815 | private void AddTimeLine()
816 | {
817 | if (_axisCanvas != null)
818 | {
819 | _axisCanvas.Children.Clear();
820 | for (int i = 0; i < 24; i++)
821 | {
822 | _axisCanvas.Children.Add(new Line()
823 | {
824 | X1 = Dial_Cell_H * i,
825 | Y1 = 0,
826 | X2 = Dial_Cell_H * i,
827 | Y2 = 5,
828 | StrokeThickness = 1
829 | });
830 | }
831 | }
832 | }
833 |
834 | ///
835 | /// 初始化时间轴
836 | ///
837 | private void AddHisPie()
838 | {
839 | if (_videoHistoryPanel != null && HisVideoSources != null && HisVideoSources.Count() > 0)
840 | {
841 | _videoHistoryPanel.Children.Clear();
842 | foreach (var item in HisVideoSources)
843 | {
844 | Dictionary, bool> dic = MathToTimeSp(item.AxisHistoryTimeList);
845 | DisplayData(dic);
846 | }
847 | }
848 | }
849 |
850 | ///
851 | /// 计算填充时间轴查询结果
852 | ///
853 | private void DisplayData(Dictionary, bool> dic)
854 | {
855 | DateTime serTime = StartTime;
856 | Canvas TimeCanvas = new Canvas() { Width = (_scrollViewer.ActualWidth - 10) * Slider_Magnification };
857 | foreach (var item in dic)
858 | {
859 | TimeCanvas.Children.Add(new Rectangle()
860 | {
861 | Width = item.Key.Value * Dial_Cell_M,
862 | Height = item.Value ? 16 : 0,
863 | Margin = new Thickness(serTime.Hour * Dial_Cell_H + serTime.Minute * Dial_Cell_M + serTime.Second * Dial_Cell_S, 0, 0, 0)
864 | });
865 | serTime = serTime.AddMinutes(item.Key.Value);
866 | }
867 | _videoHistoryPanel.Children.Add(TimeCanvas);
868 | }
869 |
870 | ///
871 | /// 计算断续时间轴
872 | ///
873 | ///
874 | ///
875 | private Dictionary, bool> MathToTimeSp(char[] region)
876 | {
877 | Dictionary, bool> dic = new Dictionary, bool>();
878 | string regStr = new string(region.Select(x => x == '\0' ? x = '0' : '1').ToArray());
879 | foreach (Match item in Regex.Matches(regStr, "(.)\\1*"))
880 | {
881 | if (item.Success)
882 | {
883 | dic.Add(new KeyValuePair(dic.Count + 1, item.Value.Length), item.Value.Contains('1') ? true : false);
884 | }
885 | }
886 | return dic;
887 | }
888 |
889 | ///
890 | /// 初始化下载数据模板
891 | ///
892 | private void Down_ListBox_Template()
893 | {
894 | DataTemplate dataTemplate = new DataTemplate();
895 | FrameworkElementFactory topElement = CreateTopElement();
896 |
897 | FrameworkElementFactory downPath = CreatePathElement(GeometryDown, "下载历史");
898 | FrameworkElementFactory downViewBox = CreateViewBoxElement(VideoAxisActionType.Dwon.ToString(), downPath);
899 | topElement.AppendChild(downViewBox);
900 |
901 | FrameworkElementFactory favoritePath = CreatePathElement(GeometryFavorite, "收藏历史");
902 | FrameworkElementFactory favoriteViewBox = CreateViewBoxElement(VideoAxisActionType.Favorite.ToString(), favoritePath);
903 | topElement.AppendChild(favoriteViewBox);
904 |
905 | FrameworkElementFactory openPath = CreatePathElement(GeometryOpen, "打开视频");
906 | FrameworkElementFactory openViewBox = CreateViewBoxElement(VideoAxisActionType.Open.ToString(), openPath);
907 | topElement.AppendChild(openViewBox);
908 |
909 | dataTemplate.VisualTree = topElement;
910 | _downButtonListBox.ItemTemplate = dataTemplate;
911 | }
912 |
913 | ///
914 | /// 创建顶层数据模板容器
915 | ///
916 | ///
917 | private FrameworkElementFactory CreateTopElement()
918 | {
919 | FrameworkElementFactory frameworkElementFactory = new FrameworkElementFactory(typeof(StackPanel));
920 | frameworkElementFactory.SetValue(StackPanel.HeightProperty, 16.00);
921 | frameworkElementFactory.SetValue(StackPanel.MarginProperty, new Thickness(0, 4, 5, 0));
922 | frameworkElementFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
923 | return frameworkElementFactory;
924 | }
925 |
926 | ///
927 | /// 创建Path元素模板
928 | ///
929 | ///
930 | ///
931 | ///
932 | private FrameworkElementFactory CreatePathElement(string GeometryPath, string ToolTipStr)
933 | {
934 | FrameworkElementFactory path = new FrameworkElementFactory(typeof(Path));
935 | path.SetValue(CursorProperty, Cursors.Hand);
936 | path.SetValue(Path.DataProperty, Geometry.Parse(GeometryPath));
937 | path.SetValue(Path.FillProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#c8c7c3")));
938 | path.SetValue(ToolTipProperty, ToolTipStr);
939 | return path;
940 | }
941 |
942 | ///
943 | /// 创建ViewBox元素模板
944 | ///
945 | ///
946 | ///
947 | ///
948 | ///
949 | private FrameworkElementFactory CreateViewBoxElement(string NameStr, FrameworkElementFactory pathChild)
950 | {
951 | FrameworkElementFactory viewBox = new FrameworkElementFactory(typeof(Viewbox));
952 | viewBox.SetValue(HeightProperty, 14.00);
953 | viewBox.SetValue(WidthProperty, 14.00);
954 | viewBox.SetValue(MarginProperty, new Thickness(10, 0, 0, 2));
955 | viewBox.SetValue(NameProperty, NameStr);
956 | viewBox.AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(viewBox_LeftMouseButtonDown));
957 | viewBox.AppendChild(pathChild);
958 | return viewBox;
959 | }
960 |
961 | ///
962 | /// 模板触发路由事件
963 | ///
964 | ///
965 | ///
966 | private void viewBox_LeftMouseButtonDown(object sender, MouseButtonEventArgs e)
967 | {
968 | Viewbox viewBox = sender as Viewbox;
969 | VideoStateItem videoState = viewBox.DataContext as VideoStateItem;
970 | if (videoState != null && viewBox != null)
971 | {
972 | VideoStateAxisRoutedEventArgs args = new VideoStateAxisRoutedEventArgs(AxisDownRoutedEvent, this)
973 | {
974 | CameraChecked = videoState.CameraChecked,
975 | DownAndFavoirteHaveVideo = DownAndFavoriteHaveVideo(videoState.AxisHistoryTimeList)
976 | };
977 | switch ((VideoAxisActionType)Enum.Parse(typeof(VideoAxisActionType), viewBox.Name))
978 | {
979 | case VideoAxisActionType.Dwon:
980 | args.ActionType = VideoAxisActionType.Dwon;
981 | break;
982 | case VideoAxisActionType.Favorite:
983 | args.ActionType = VideoAxisActionType.Favorite;
984 | break;
985 | case VideoAxisActionType.Open:
986 | args.ActionType = VideoAxisActionType.Open;
987 | break;
988 | }
989 | this.RaiseEvent(args);
990 | }
991 | }
992 |
993 | ///
994 | /// 判断是否有视频
995 | ///
996 | ///
997 | ///
998 | private bool DownAndFavoriteHaveVideo(char[] VideoList)
999 | {
1000 | if (!ClipOff)
1001 | {
1002 | return VideoList.Select(x => x == '\0' ? x = '0' : '1').ToArray().Contains('1') ? true : false;
1003 | }
1004 | else
1005 | {
1006 | Dictionary, bool> dic = MathToTimeSp(VideoList);
1007 | DateTime serTime = StartTime;
1008 | List booList = new List();
1009 | foreach (var item in dic)
1010 | {
1011 | DateTime end_Time = serTime.AddMinutes(item.Key.Value);
1012 | booList.Add(((serTime < ClipStartTime && ClipStartTime < end_Time) || (serTime < ClipEndTime && ClipEndTime < end_Time)) && item.Value ? true : false);
1013 | serTime = serTime.AddMinutes(item.Key.Value);
1014 | }
1015 | return booList.Contains(true) ? true : false;
1016 | }
1017 | }
1018 |
1019 | ///
1020 | /// 获得实例项
1021 | ///
1022 | public override void OnApplyTemplate()
1023 | {
1024 | _timePanel = GetTemplateChild(Parid_timePanel) as Canvas;
1025 | _timeLine = GetTemplateChild(Parid_timeLine) as Canvas;
1026 | _axisCanvas = GetTemplateChild(Parid_axisCanvas) as Canvas;
1027 | _videoHistoryPanel = GetTemplateChild(Parid_videoHistoryPanel) as StackPanel;
1028 | _axisCanvasTimeText = GetTemplateChild(Parid__axisCanvasTimeText) as Canvas;
1029 | _clipCanvas = GetTemplateChild(Parid_clipCanvas) as Canvas;
1030 | _clipStackPanel = GetTemplateChild(Parid_clipStackPanel) as StackPanel;
1031 | if ((_clipOff = GetTemplateChild(Parid_clipOff) as CheckBox) != null)
1032 | {
1033 | _clipOff.Checked += new RoutedEventHandler(Clip_UnChecked_Checked);
1034 | _clipOff.Unchecked += new RoutedEventHandler(Clip_UnChecked_Checked);
1035 | }
1036 | if ((_zoomSlider = GetTemplateChild(Parid_zoomSlider) as Slider) != null)
1037 | {
1038 | _zoomSlider.ValueChanged += new RoutedPropertyChangedEventHandler(_zoomSlider_ValueChanged);
1039 | }
1040 | if ((_timePoint = GetTemplateChild(Parid_timePoint) as Grid) != null)
1041 | {
1042 | _timePoint.MouseLeftButtonDown += new MouseButtonEventHandler(timePoint_MouseLeftButtonDown);
1043 | _timePoint.MouseLeftButtonUp += new MouseButtonEventHandler(timePoint_MouseLeftButtonUp);
1044 | _timePoint.MouseMove += new MouseEventHandler(timePoint_MouseMove);
1045 | }
1046 | if ((_scrollViewer = GetTemplateChild(Parid_scrollViewer) as ScrollViewer) != null)
1047 | {
1048 | _scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewer_Changed);
1049 | }
1050 | if ((_currentTime = GetTemplateChild(Parid_currentTime) as TextBlock) != null)
1051 | {
1052 | _currentTime.Text = StartTime.ToString("yyyy-MM-dd 00:00:00");
1053 | }
1054 | if ((_clipEndBorder = GetTemplateChild(Parid_clipEndBorder) as Border) != null)
1055 | {
1056 | _clipEndBorder.MouseLeftButtonDown += new MouseButtonEventHandler(Clip_MouseLeftButtonDown);
1057 | _clipEndBorder.MouseMove += new MouseEventHandler(Clip_MouseMove);
1058 | _clipEndBorder.MouseLeftButtonUp += new MouseButtonEventHandler(Clip_MouseLeftButtonUp);
1059 | }
1060 | if ((_clipAreaBorder = GetTemplateChild(Parid_clipAreaBorder) as Border) != null)
1061 | {
1062 | _clipAreaBorder.MouseLeftButtonDown += new MouseButtonEventHandler(Clip_MouseLeftButtonDown);
1063 | _clipAreaBorder.MouseMove += new MouseEventHandler(Clip_MouseMove);
1064 | _clipAreaBorder.MouseLeftButtonUp += new MouseButtonEventHandler(Clip_MouseLeftButtonUp);
1065 | }
1066 | if ((_clipStartBorder = GetTemplateChild(Parid_clipStartBorder) as Border) != null)
1067 | {
1068 | _clipStartBorder.MouseLeftButtonDown += new MouseButtonEventHandler(Clip_MouseLeftButtonDown);
1069 | _clipStartBorder.MouseMove += new MouseEventHandler(Clip_MouseMove);
1070 | _clipStartBorder.MouseLeftButtonUp += new MouseButtonEventHandler(Clip_MouseLeftButtonUp);
1071 | }
1072 | if ((_clipStateTimeTextBlock = GetTemplateChild(Parid_clipStateTimeTextBlock) as TextBlock) != null)
1073 | {
1074 | Binding binding = new Binding("ClipStartTime") { Source = this, StringFormat = " [ yyyy-MM-dd ] HH:mm:ss " };
1075 | _clipStateTimeTextBlock.SetBinding(TextBlock.TextProperty, binding);
1076 | }
1077 | if ((_clipEndTimeTextBlock = GetTemplateChild(Parid_clipEndTimeTextBlock) as TextBlock) != null)
1078 | {
1079 | Binding binding = new Binding("ClipEndTime") { Source = this, StringFormat = " [ yyyy-MM-dd ] HH:mm:ss " };
1080 | _clipEndTimeTextBlock.SetBinding(TextBlock.TextProperty, binding);
1081 | }
1082 | if ((_cameraListBox = GetTemplateChild(Parid_cameraListBox) as ListBox) != null)
1083 | {
1084 | Binding binding = new Binding("HisVideoSources") { Source = this };
1085 | _cameraListBox.SetBinding(ListBox.ItemsSourceProperty, binding);
1086 | }
1087 | if ((_downButtonListBox = GetTemplateChild(Parid_downButtonListBox) as ListBox) != null)
1088 | {
1089 | Binding binding = new Binding("HisVideoSources") { Source = this };
1090 | _downButtonListBox.SetBinding(ListBox.ItemsSourceProperty, binding);
1091 | Down_ListBox_Template();
1092 | }
1093 | }
1094 |
1095 | ///
1096 | /// 将原始控件的样式覆盖
1097 | ///
1098 | static VideoStateAxisControl()
1099 | {
1100 | DefaultStyleKeyProperty.OverrideMetadata(typeof(VideoStateAxisControl), new FrameworkPropertyMetadata(typeof(VideoStateAxisControl)));
1101 | }
1102 |
1103 | #endregion
1104 | }
1105 |
1106 | ///
1107 | /// 时间轴事件参数类
1108 | ///
1109 | public class VideoStateAxisRoutedEventArgs : RoutedEventArgs
1110 | {
1111 | ///
1112 | /// 基类构造函数
1113 | ///
1114 | ///
1115 | ///
1116 | public VideoStateAxisRoutedEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source) { }
1117 |
1118 | ///
1119 | /// 事件类型
1120 | ///
1121 | public VideoAxisActionType ActionType { get; set; }
1122 |
1123 | ///
1124 | /// 相机是否选中
1125 | ///
1126 | public bool CameraChecked { get; set; }
1127 |
1128 | ///
1129 | /// 指针时间
1130 | ///
1131 | public DateTime TimeLine { get; set; }
1132 |
1133 | ///
1134 | /// 下载或者收藏范围内是否有视频
1135 | ///
1136 | public bool DownAndFavoirteHaveVideo { get; set; }
1137 | }
1138 |
1139 | ///
1140 | /// 时间轴控件事件类型
1141 | ///
1142 | public enum VideoAxisActionType
1143 | {
1144 | [Description("下载")]
1145 | Dwon,
1146 |
1147 | [Description("收藏")]
1148 | Favorite,
1149 |
1150 | [Description("打开")]
1151 | Open
1152 | }
1153 |
1154 | ///
1155 | /// 时间轴对象
1156 | ///
1157 | public class VideoStateItem : INotifyPropertyChanged
1158 | {
1159 | private string _cameraName;
1160 | public string CameraName
1161 | {
1162 | get => _cameraName;
1163 | set { _cameraName = value;OnPropertyChanged("CameraName"); }
1164 | }
1165 |
1166 | private bool _cameraChedcked;
1167 | ///
1168 | /// 相机是否选中
1169 | ///
1170 | public bool CameraChecked
1171 | {
1172 | get => _cameraChedcked;
1173 | set { _cameraChedcked = value; OnPropertyChanged("CameraChecked"); }
1174 | }
1175 |
1176 | private char[] _axisHistoryTimeList;
1177 | ///
1178 | /// 相机历史视频视频时间集
1179 | ///
1180 | public char[] AxisHistoryTimeList
1181 | {
1182 | get => _axisHistoryTimeList;
1183 | set { _axisHistoryTimeList = value; OnPropertyChanged("AxisHistoryTimeList"); }
1184 | }
1185 |
1186 | public event PropertyChangedEventHandler PropertyChanged;
1187 |
1188 | private void OnPropertyChanged(string propertyName)
1189 | {
1190 | PropertyChangedEventHandler handler = this.PropertyChanged;
1191 | if (handler != null)
1192 | {
1193 | handler(this, new PropertyChangedEventArgs(propertyName));
1194 | }
1195 | }
1196 | }
1197 | }
1198 |
--------------------------------------------------------------------------------