我有一个自定义包创建为Visual Studio扩展。对于我的项目文件,我创建了两个新的自定义属性页面。只有这两个显示在我的项目的属性窗口中。一切都可以在属性页面级别使用Dirty标志工作,这意味着,当我更改某些内容时,单个选项卡设置为脏,并且当存储信息时,它会变回不脏。
但我的问题是:一旦我打开属性页面,视图的主Tab(显示项目名称)包含脏标志(一个小星星),我无法解决这个问题。我必须在哪个属性中设置“不脏”,以便整个页面显示为“不脏”。
祝你好运, 马丁
答案 0 :(得分:0)
我记得MSDF论坛上有一些相关的主题(Visual Studio可扩展性) - 请参阅here。
我不太确定,但我在“Need sample code for custom property pages”主题中在MSDN论坛(VSX论坛)上发布的示例对我来说很合适。
P.S。而且您始终可以报告VSX bug on Microsoft Connent。
请参阅下面的自定义属性页示例,其余相关代码示例也可用于上面提到的MSDN线程。
1 using System;
2 using System.Diagnostics;
3 using System.Drawing;
4 using System.IO;
5 using System.Runtime.InteropServices;
6 using System.Text.RegularExpressions;
7 using System.Windows.Forms;
8
9 namespace MyProjectProperties
10 {
11 [Guid(Guids.RealCustomPropertyPageGuidString)]
12 public partial class RealCustomPropertyPage : CustomPropertyPage
13 {
14 ...
15
16 #region Constructors
17
18 public RealCustomPropertyPage()
19 : base()
20 {
21 InitializeComponent();
22 Title = ResMgr.GetString(TextKeys.RealCustomPropertyPageCaption);
23 }
24
25 #endregion
26
27
28 #region Overriden Methods
29
30 protected override void Initialize()
31 {
32 AddComboBoxItems(cboOutputType, OutputTypeManager.Application, OutputTypeManager.Library);
33 AddComboBoxItems(cboTargetVersion, TargetVersionManager.Flash7, TargetVersionManager.Flash8);
34
35 txtAssemblyName.TextChanged += new EventHandler(OnPropertyChanged);
36 txtDefaultNamespace.TextChanged += new EventHandler(OnPropertyChanged);
37 txtMainClass.TextChanged += new EventHandler(OnPropertyChanged);
38 txtInputSwfLocation.TextChanged += new EventHandler(OnRefreshControlStateChanged);
39 txtOutputPath.TextChanged += new EventHandler(OnPropertyChanged);
40 txtFrameParameter.TextChanged += new EventHandler(OnPropertyChanged);
41 txtFrameRate.TextChanged += new EventHandler(OnPropertyChanged);
42 txtWidth.TextChanged += new EventHandler(OnPropertyChanged);
43 txtHeight.TextChanged += new EventHandler(OnPropertyChanged);
44 txtColorPreview.TextChanged += new EventHandler(OnColorPreviewChanged);
45 txtAdditionalParams.TextChanged += new EventHandler(OnPropertyChanged);
46
47 cboOutputType.SelectedIndexChanged += new EventHandler(OnRefreshControlStateChanged);
48 cboTargetVersion.SelectedIndexChanged += new EventHandler(OnPropertyChanged);
49
50 chkInputSwfLocation.CheckedChanged += new EventHandler(OnRefreshControlStateChanged);
51 chkKeepParameter.CheckedChanged += new EventHandler(OnPropertyChanged);
52 chkFrameParameter.CheckedChanged += new EventHandler(OnPropertyChanged);
53 chkUsePrecompiledMxClasses.CheckedChanged += new EventHandler(OnPropertyChanged);
54 chkUseTypeInference.CheckedChanged += new EventHandler(OnPropertyChanged);
55 chkUseStrictCompilation.CheckedChanged += new EventHandler(OnPropertyChanged);
56
57 btnBrowseInputSwf.Click += new EventHandler(OnBrowseInputSwfClicked);
58 btnBrowseMainClass.Click += new EventHandler(OnBrowseMainClassClicked);
59 btnSelectBackgroundColor.Click += new EventHandler(OnSelectBackgroundColorClicked);
60 btnSetOutputPath.Click += new EventHandler(OnBrowseOutputPathClicked);
61
62 RefreshControlState();
63 }
64
65 protected override void FillProperties()
66 {
67 Fill(txtAssemblyName, Property.AssemblyName);
68 Fill(txtDefaultNamespace, Property.DefaultNamespace);
69 Fill(txtMainClass, Property.MainClass);
70 Fill(txtOutputPath, Property.AsOutputPath);
71 Fill(txtInputSwfLocation, Property.InputSwfLocation);
72 Fill(txtFrameParameter, Property.FrameParameter);
73 Fill(txtFrameRate, Property.FrameRate);
74 Fill(txtWidth, Property.Width);
75 Fill(txtHeight, Property.Height);
76 Fill(txtAdditionalParams, Property.AdditionalParams);
77
78 Fill(lblColorPreview, Property.BackgroundColor);
79
80 Fill(cboTargetVersion, Property.TargetVersion);
81 Fill(cboOutputType, Property.OutputType);
82
83 Fill(chkInputSwfLocation, Property.UseInputSwf);
84 Fill(chkKeepParameter, Property.KeepInputClasses);
85 Fill(chkFrameParameter, Property.UseFrameParameter);
86 Fill(chkUsePrecompiledMxClasses, Property.UsePrecompiledMxClasses);
87 Fill(chkUseTypeInference, Property.UseTypeInference);
88 Fill(chkUseStrictCompilation, Property.UseStrictCompilation);
89 }
90
91 protected override bool CheckInput()
92 {
93 bool valid = true;
94
95 valid &= CheckSwfInputFileValid();
96 valid &= CheckFrameRateValid();
97 valid &= CheckWidthValid();
98 valid &= CheckHeightValid();
99 valid &= CheckFrameValid();
100 valid &= CheckOutputPathValid();
101
102 return valid;
103 }
104
105 protected override void ApplyChanges()
106 {
107 bool needReParse = GetComboValue(cboTargetVersion) != GetProperty(Property.TargetVersion);
108
109 Apply(txtAssemblyName, Property.AssemblyName);
110 Apply(txtDefaultNamespace, Property.DefaultNamespace);
111 Apply(txtMainClass, Property.MainClass);
112 Apply(txtOutputPath, Property.AsOutputPath);
113 Apply(txtInputSwfLocation, Property.InputSwfLocation);
114 Apply(txtFrameParameter, Property.FrameParameter);
115 Apply(txtFrameRate, Property.FrameRate);
116 Apply(txtWidth, Property.Width);
117 Apply(txtHeight, Property.Height);
118 Apply(txtAdditionalParams, Property.AdditionalParams);
119
120 Apply(lblColorPreview, Property.BackgroundColor);
121
122 Apply(cboOutputType, Property.OutputType);
123 Apply(cboTargetVersion, Property.TargetVersion);
124
125 Apply(chkInputSwfLocation, Property.UseInputSwf);
126 Apply(chkKeepParameter, Property.KeepInputClasses);
127 Apply(chkFrameParameter, Property.UseFrameParameter);
128 Apply(chkUsePrecompiledMxClasses, Property.UsePrecompiledMxClasses);
129 Apply(chkUseTypeInference, Property.UseTypeInference);
130 Apply(chkUseStrictCompilation, Property.UseStrictCompilation);
131
132 // Re-parse with new target type applied
133 if (needReParse && SettingManager.EnableIntelliSense && NeutronKeeper.Registered)
134 {
135 string property = GetProperty(Property.TargetVersion);
136 string directory = TargetVersionManager.DefineDirectory(property);
137 Debug.Assert(Directory.Exists(directory));
138
139 SymbolTable cache = ((AsProjectNode)ProjectMgr).GetCache();
140 cache.ParseSourcesFromDirectory(directory, true, true);
141 }
142 }
143
144 #endregion
145
146
147 #region Private Methods
148
149 private void OnPropertyChanged(object sender, EventArgs e)
150 {
151 MarkPageChanged();
152 }
153
154 private void OnRefreshControlStateChanged(object sender, EventArgs e)
155 {
156 RefreshControlState();
157 MarkPageChanged();
158 }
159
160 private void OnBrowseOutputPathClicked(object sender, EventArgs e)
161 {
162 FolderBrowserDialog dialog = new FolderBrowserDialog();
163
164 string projectDir = GetProperty(Property.MSBuildProjectDirectory);
165 PropertyHelper.SetPaths(dialog, projectDir, txtOutputPath.Text);
166
167 if (DialogResult.OK == dialog.ShowDialog())
168 {
169 txtOutputPath.Text = PathHelper.MakeRelative(projectDir, dialog.SelectedPath);
170 MarkPageChanged();
171 }
172 }
173
174 private void OnSelectBackgroundColorClicked(object sender, EventArgs e)
175 {
176 ColorDialog dialog = new ColorDialog();
177 dialog.Color = lblColorPreview.BackColor;
178 if (DialogResult.OK == dialog.ShowDialog())
179 {
180 SetColorPreview(lblColorPreview, dialog.Color);
181 MarkPageChanged();
182 }
183 }
184
185 private void OnBrowseMainClassClicked(object sender, EventArgs e)
186 {
187 OpenFileDialog dialog = new OpenFileDialog();
188 dialog.Title = ResMgr.GetString(TextKeys.BrowseMainClassTitle);
189 dialog.Filter = ResMgr.GetString(TextKeys.BrowseMainClassFilter);
190
191 string projectDir = GetProperty(Property.MSBuildProjectDirectory);
192 PropertyHelper.SetPaths(dialog, projectDir, txtMainClass.Text);
193
194 if (DialogResult.OK == dialog.ShowDialog())
195 {
196 txtMainClass.Text = PathHelper.MakeRelative(projectDir, dialog.FileName);
197 OnPropertyChanged(sender, e);
198 }
199 }
200
201 private void OnBrowseInputSwfClicked(object sender, EventArgs e)
202 {
203 OpenFileDialog dialog = new OpenFileDialog();
204 dialog.Title = ResMgr.GetString(TextKeys.BrowseInputSwfTitle);
205 dialog.Filter = ResMgr.GetString(TextKeys.BrowseInputSwfFilter);
206
207 string projectDir = GetProperty(Property.MSBuildProjectDirectory);
208 PropertyHelper.SetPaths(dialog, projectDir, txtInputSwfLocation.Text);
209
210 if (DialogResult.OK == dialog.ShowDialog())
211 {
212 txtInputSwfLocation.Text = PathHelper.MakeRelative(projectDir, dialog.FileName);
213 OnPropertyChanged(sender, e);
214 }
215 }
216
217 private void OnColorPreviewChanged(object sender, EventArgs e)
218 {
219 Match match = _hexColorRegex.Match(txtColorPreview.Text.Trim());
220 if (match.Success)
221 {
222 SetColorPreview(lblColorPreview, HexStringToColor(match.Captures[0].Value));
223 }
224 }
225
226 private void RefreshControlState()
227 {
228 // Input swiff file block related
229 bool allowToSelectInputSwf = chkInputSwfLocation.Checked;
230 bool isInputSwfHasValue = txtInputSwfLocation.Text.Trim().Length > 0;
231
232 txtInputSwfLocation.Enabled = allowToSelectInputSwf;
233 btnBrowseInputSwf.Enabled = allowToSelectInputSwf;
234 chkKeepParameter.Enabled = allowToSelectInputSwf && isInputSwfHasValue;
235 chkUsePrecompiledMxClasses.Enabled = allowToSelectInputSwf && isInputSwfHasValue;
236
237 // Application settings group related
238 gbxApplicationSettings.Enabled = (GetComboValue(cboOutputType) == OutputTypeManager.Application);
239 }
240
241 private bool CheckFrameRateValid()
242 {
243 return IsPositiveInteger(txtFrameRate.Text, "Invalid Frame Rate value.");
244 }
245
246 private bool CheckFrameValid()
247 {
248 return IsPositiveInteger(txtFrameParameter.Text, "Invalid Target Frame value.");
249 }
250
251 private bool CheckHeightValid()
252 {
253 return IsPositiveInteger(txtHeight.Text, "Invalid Height value.");
254 }
255
256 private bool CheckWidthValid()
257 {
258 return IsPositiveInteger(txtWidth.Text, "Invalid Width value.");
259 }
260
261 private bool IsPositiveInteger(string toParse, string errorMessage)
262 {
263 try
264 {
265 uint.Parse(toParse);
266 }
267 catch
268 {
269 _logger.Info(errorMessage);
270 MessageBox.Show(errorMessage);
271 return false;
272 }
273 return true;
274 }
275
276 private bool CheckSwfInputFileValid()
277 {
278 ...
279 }
280
281 private bool CheckOutputPathValid()
282 {
283 ...
284 }
285
286 private void Fill(Label label, Property property)
287 {
288 string backgroundColor = ProjectMgr.GetProjectProperty(property.ToString(), true);
289 SetColorPreview(label, HexStringToColor(backgroundColor));
290 }
291
292 private void SetColorPreview(Label label, Color color)
293 {
294 txtColorPreview.Text = label.Text = ColorTranslator.ToHtml(color);
295 label.BackColor = color;
296 }
297
298 private void Apply(Label acceptor, Property property)
299 {
300 string hexString = ColorToHexString(acceptor.BackColor);
301 ProjectMgr.SetProjectProperty(property.ToString(), hexString);
302 }
303
304 private string FilterDirectoryPath(string dirPath)
305 {
306 if (dirPath.Split(Path.GetInvalidPathChars()).Length > 1)
307 {
308 dirPath = dirPath.Trim();
309 foreach(char invalidCharacter in Path.GetInvalidPathChars())
310 {
311 dirPath = dirPath.Replace(invalidCharacter.ToString(), string.Empty);
312 }
313 }
314 return dirPath;
315 }
316
317
318 #region HEX <-> Color convertions
319
320 ... skipped ...
321
322 #endregion
323
324
325 #endregion
326 }
327 }