跳到主要内容

github/tai

公开

Tai · Windows 软件与网站使用时长统计。上游 Planshit/Tai 的源码镜像,非灵栈原创;MIT 许可。来源:https://github.com/Planshit/Tai 。本次为手动同步,暂不提供安装包。

浏览文件

SettingPanelMultiItem.cs

333 行 · 11.8 KB历史下载
1using Core.Models.Config;
2using System;
3using System.Collections;
4using System.Collections.Generic;
5using System.Collections.ObjectModel;
6using System.Collections.Specialized;
7using System.Diagnostics;
8using System.Linq;
9using System.Reflection;
10using System.Text;
11using System.Text.RegularExpressions;
12using System.Threading.Tasks;
13using System.Windows;
14using System.Windows.Controls;
15using UI.Controls.Button;
16using UI.Controls.Input;
17using UI.Controls.List;
18
19namespace UI.Controls.SettingPanel
20{
21 public class SettingPanelMultiItem : Control
22 {
23 /// <summary>
24 /// 所有设置数据
25 /// </summary>
26 public Dictionary<string, List<string>> SettingData { get { return (Dictionary<string, List<string>>)GetValue(SettingDataProperty); } set { SetValue(SettingDataProperty, value); } }
27 public static readonly DependencyProperty SettingDataProperty = DependencyProperty.Register("SettingData", typeof(Dictionary<string, List<string>>), typeof(SettingPanelMultiItem));
28 public bool Fold { get { return (bool)GetValue(FoldProperty); } set { SetValue(FoldProperty, value); } }
29 public static readonly DependencyProperty FoldProperty = DependencyProperty.Register("Fold", typeof(bool), typeof(SettingPanelMultiItem), new PropertyMetadata(false));
30
31 public object Data { get { return (object)GetValue(DataProperty); } set { SetValue(DataProperty, value); } }
32 public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(SettingPanelMultiItem));
33
34 public Command OnRemoveAction { get { return (Command)GetValue(OnRemoveActionProperty); } set { SetValue(OnRemoveActionProperty, value); } }
35 public static readonly DependencyProperty OnRemoveActionProperty = DependencyProperty.Register("OnRemoveAction", typeof(Command), typeof(SettingPanelMultiItem));
36 public Command OnFoldAction { get { return (Command)GetValue(OnFoldActionProperty); } set { SetValue(OnFoldActionProperty, value); } }
37 public static readonly DependencyProperty OnFoldActionProperty = DependencyProperty.Register("OnFoldAction", typeof(Command), typeof(SettingPanelMultiItem));
38 public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } }
39 public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(SettingPanelMultiItem));
40 public event EventHandler DataChanged;
41
42 private StackPanel Container;
43 private object configData;
44 private IconButton FoldBtn;
45 public SettingPanelMultiItem()
46 {
47 DefaultStyleKey = typeof(SettingPanelMultiItem);
48
49 if (SettingData == null)
50 {
51 SettingData = new Dictionary<string, List<string>>();
52 }
53 }
54 public override void OnApplyTemplate()
55 {
56 base.OnApplyTemplate();
57 Container = GetTemplateChild("Container") as StackPanel;
58 FoldBtn = GetTemplateChild("FoldBtn") as IconButton;
59
60 OnFoldAction = new Command(new Action<object>(FoldAction));
61 Render();
62 }
63
64 private void FoldAction(object obj)
65 {
66 Fold = !Fold;
67 if (Fold)
68 {
69 FoldBtn.Icon = Base.IconTypes.ChevronDown;
70
71 FoldBtn.ToolTip = "展开";
72 }
73 else
74 {
75 FoldBtn.Icon = Base.IconTypes.ChevronUp;
76
77 FoldBtn.ToolTip = "收起";
78
79 }
80 }
81
82 private void Render()
83 {
84 if (Container == null)
85 {
86 return;
87 }
88
89 Container.Children.Clear();
90
91 configData = Activator.CreateInstance(Data.GetType());
92
93 // 遍历方法特性
94 foreach (PropertyInfo pi in Data.GetType().GetProperties())
95 {
96 foreach (Attribute attr in pi.GetCustomAttributes(true))
97 {
98 if (attr is ConfigAttribute)
99 {
100 ConfigAttribute attribute = (ConfigAttribute)attr;
101
102 if (pi.PropertyType == typeof(string))
103 {
104 // 输入框
105 RenderTextBox(attribute, pi);
106 }
107 else if (pi.PropertyType == typeof(List<string>))
108 {
109 // String 集合
110 RenderStringList(attribute, pi);
111 }
112 }
113 }
114 }
115 }
116
117 private void RenderStringList(ConfigAttribute attribute, PropertyInfo pi)
118 {
119 var title = new SettingPanelItem();
120 title.Name = attribute.Name;
121 title.Description = attribute.Description;
122
123 Container.Children.Add(title);
124
125 var list = pi.GetValue(Data) as List<string>;
126
127 if (SettingData.ContainsKey(pi.Name))
128 {
129 SettingData[pi.Name] = SettingData[pi.Name].Concat(list).ToList();
130 }
131 else
132 {
133 SettingData.Add(pi.Name, list);
134 }
135
136 var listControl = new BaseList();
137
138 listControl.Loaded += (sender, args) =>
139 {
140 listControl.Items.CollectionChanged += (o, e) =>
141 {
142 var newData = new List<string>();
143 foreach (var item in listControl.Items)
144 {
145 newData.Add(item.ToString());
146 }
147 pi.SetValue(configData, newData);
148 Data = configData;
149 DataChanged?.Invoke(this, EventArgs.Empty);
150 };
151 //((INotifyCollectionChanged)listControl.Items).CollectionChanged += (sender2, e) =>
152 //{
153 // var newData = new List<string>();
154 // foreach (var item in listControl.Items)
155 // {
156 // newData.Add(item.ToString());
157 // }
158 // pi.SetValue(configData, newData);
159 // Data = configData;
160 // DataChanged?.Invoke(this, EventArgs.Empty);
161 //};
162 };
163 listControl.Margin = new Thickness(15, 0, 15, 10);
164
165 if (list != null)
166 {
167 foreach (string item in list)
168 {
169 listControl.Items.Add(item);
170 }
171 }
172 else
173 {
174 list = new List<string>();
175 }
176 var contextMenu = new ContextMenu();
177
178 var contextMenuItemDel = new MenuItem();
179 contextMenuItemDel.Header = "移除";
180 contextMenuItemDel.Click += (e, c) =>
181 {
182 listControl.Items.Remove(listControl.SelectedItem);
183 };
184 contextMenu.Items.Add(contextMenuItemDel);
185 listControl.ContextMenu = contextMenu;
186
187
188 var addInputBox = new InputBox();
189 addInputBox.Placeholder = attribute.Name;
190 addInputBox.Margin = new Thickness(0, 0, 10, 0);
191
192 var addBtn = new Button.Button();
193 //addBtn.Margin = new Thickness(15, 0, 15, 10);
194 addBtn.Content = "添加";
195
196 addBtn.Click += (e, c) =>
197 {
198 addInputBox.Error = attribute.Name + (addInputBox.Text == String.Empty ? "不能为空" : "已存在");
199
200 if (addInputBox.Text == String.Empty || list.Contains(addInputBox.Text))
201 {
202 addInputBox.ShowError();
203 return;
204 }
205
206 // 判断重复
207 if (!attribute.IsCanRepeat && SettingData[pi.Name].Contains(addInputBox.Text))
208 {
209 addInputBox.ShowError();
210 return;
211 }
212
213 //list.Add(addInputBox.Text);
214 listControl.Items.Add(addInputBox.Text);
215 addInputBox.Text = String.Empty;
216
217
218
219 };
220 pi.SetValue(configData, list);
221 Container.Children.Add(listControl);
222
223 var inputPanel = new Grid();
224 inputPanel.ColumnDefinitions.Add(
225 new ColumnDefinition()
226 {
227 Width = new GridLength(10, GridUnitType.Star)
228 });
229 inputPanel.ColumnDefinitions.Add(
230 new ColumnDefinition()
231 {
232 Width = new GridLength(2, GridUnitType.Star)
233 });
234 inputPanel.Margin = new Thickness(15, 10, 15, 10);
235 Grid.SetColumn(addInputBox, 0);
236 Grid.SetColumn(addBtn, 1);
237 inputPanel.Children.Add(addInputBox);
238 inputPanel.Children.Add(addBtn);
239 Container.Children.Add(inputPanel);
240
241
242 }
243 private void RenderTextBox(ConfigAttribute attribute, PropertyInfo pi)
244 {
245 string value = (string)pi.GetValue(Data);
246
247 if (SettingData.ContainsKey(pi.Name))
248 {
249 SettingData[pi.Name].Add(value);
250 }
251 else
252 {
253 SettingData.Add(pi.Name, new List<string>()
254 {
255 value
256 });
257 }
258
259
260 var textBox = new InputBox();
261 textBox.Text = value;
262 textBox.Placeholder = attribute.Name;
263 textBox.Width = 125;
264 textBox.TextChanged += (e, c) =>
265 {
266 textBox.Error = attribute.Name + (textBox.Text == String.Empty ? "不能为空" : "已存在");
267
268 if (!attribute.IsCanRepeat)
269 {
270 if (SettingData[pi.Name].Contains(textBox.Text) && textBox.Tag.ToString() != textBox.Text)
271 {
272 textBox.ShowError();
273 return;
274 }
275 else
276 {
277 textBox.HideError();
278 }
279 }
280 if (textBox.Text == String.Empty)
281 {
282 textBox.ShowError();
283 }
284 else
285 {
286 textBox.HideError();
287 }
288 };
289 textBox.GotFocus += (e, c) =>
290 {
291 // 记录获得焦点时的数据
292 textBox.Tag = textBox.Text;
293 };
294 textBox.LostFocus += (e, c) =>
295 {
296 if (textBox.Text == String.Empty)
297 {
298 textBox.Text = textBox.Tag.ToString();
299 return;
300 }
301 if (!attribute.IsCanRepeat)
302 {
303 if (SettingData[pi.Name].Contains(textBox.Text) && textBox.Tag.ToString() != textBox.Text)
304 {
305 textBox.Text = textBox.Tag.ToString();
306 return;
307 }
308 }
309 if (attribute.IsName)
310 {
311 Title = textBox.Text;
312 }
313 pi.SetValue(configData, textBox.Text);
314 Data = configData;
315 DataChanged?.Invoke(this, EventArgs.Empty);
316
317 SettingData[pi.Name].Remove(textBox.Tag.ToString());
318 SettingData[pi.Name].Add(textBox.Text);
319
320 };
321 var item = new SettingPanelItem();
322 item.Name = attribute.Name;
323 item.Description = attribute.Description;
324 item.Content = textBox;
325 pi.SetValue(configData, textBox.Text);
326 if (attribute.IsName)
327 {
328 Title = textBox.Text;
329 }
330 Container.Children.Add(item);
331 }
332 }
333}