单击 PropertyGrid 中的事件(例如打开 file/folder 对话框)
Click events from PropertyGrid (e.g. open file/folder dialog)
我正在使用 WinForms PropertyGrid
来显示程序的各种配置设置。 属性Grid 绑定到 XML 文档,该文档已 Xmlserializer.Deserialize
-ed。这允许用户输入新值,然后将其序列化回 config.xml 文件。在某些情况下,这些属性只是数字,输入值是有意义的。但是,在其他情况下,值是文件名或目录路径,因此通过 OpenFileDialog
或 FolderBrowserDialog
输入这些值更有意义。
我希望发生的是,如果用户单击 PropertyGrid
中的文件夹或文件名单元格,UI 将打开相应的对话框,得到结果,然后将该结果输入网格,替换现有值。问题是,属性Grid 似乎不允许访问其中的控件,所以我无法响应 OnClicked 事件。
以下是我希望喜欢代码的工作方式(编辑:更新代码):
private void propertyGrid_config_Click(object sender, EventArgs e)
{
PropertyGrid grid = (PropertyGrid)sender;
PropertyDescriptor selectedItem = grid.SelectedGridItem.PropertyDescriptor;
if (selectedItem.Category == "Files & Folders")
{
if (selectedItem.DisplayName.Contains("directory"))
{
FolderBrowserDialog folder = new FolderBrowserDialog();
if (folder.ShowDialog() == DialogResult.OK)
{
selectedItem.SetValue(grid.SelectedObject, folder.SelectedPath);
grid.Refresh();
}
}
else if (selectedItem.DisplayName.Contains("file"))
{
OpenFileDialog file = new OpenFileDialog();
if (file.ShowDialog() == DialogResult.OK)
{
selectedItem.SetValue(grid.SelectedObject, file.FileName);
grid.Refresh();
}
}
}
}
我已将网格的 "Clicked" 事件设置到此处理程序,但显然这不起作用,因为它只处理容器而不处理容器中的内容。 (请注意,如果我将它基于 "PropertyChanged" 事件,则此处理程序工作正常,但这显然不是我要找的。)
有什么方法可以访问组件并创建我想要的事件吗?你会如何解决这个问题?
如果相关,这里是 属性Grid 的一些代码:
网格存在于名为 "Configuration" 的 class 中,它定义了如下所有属性:
[Description("Folder for storing Bonding Key logs")]
[Category("Files & Folders")]
[DisplayName("Log output directory")]
public string dirLogOutput { get; set; }
XML 文件将有一个对应于每个 属性 的条目,如下所示:
<dirLogOutput>C:\Users\AHoffman\Desktop\TestData</dirLogOutput>
Serializer 可以很好地将 XML 文件中的数据匹配到网格,反之亦然:
public Configuration TryLoadConfiguration(Configuration thisConfig)
{
string filename = GetConfigFilename();
try
{
if (!File.Exists(filename))
{
thisConfig.setDefaults();
}
else
{
using (var stream = File.Open(filename, FileMode.Open, FileAccess.Read))
{
var serializer = new XmlSerializer(typeof(Configuration));
thisConfig = (Configuration)serializer.Deserialize(stream);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to load configuration file during startup: " + ex.Message);
thisConfig.setDefaults();
}
return thisConfig;
}
private void SaveConfiguration(string filename, Configuration thisConfig)
{
try
{
using (var stream = File.Open(filename, FileMode.Create, FileAccess.Write))
{
var serializer = new XmlSerializer(typeof(Configuration));
serializer.Serialize(stream, thisConfig);
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to save configuration file: " + ex.Message);
}
}
我注意到 here 之前有人问过这样的问题,但没有答案。希望我能给你足够的信息让你找回一些东西。
没关系。我找到了问题的答案 here (for files) and here(对于文件夹)。
这一切都依赖于为每种类型使用自定义 UITypeEditor
。
[EditorAttribute(typeof(OpenFileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
[EditorAttribute(typeof(FolderNameEditor2), typeof(System.Drawing.Design.UITypeEditor))]
非常感谢 @Simon Mourier, @Stewy, and @tzup 的回答。
我正在使用 WinForms PropertyGrid
来显示程序的各种配置设置。 属性Grid 绑定到 XML 文档,该文档已 Xmlserializer.Deserialize
-ed。这允许用户输入新值,然后将其序列化回 config.xml 文件。在某些情况下,这些属性只是数字,输入值是有意义的。但是,在其他情况下,值是文件名或目录路径,因此通过 OpenFileDialog
或 FolderBrowserDialog
输入这些值更有意义。
我希望发生的是,如果用户单击 PropertyGrid
中的文件夹或文件名单元格,UI 将打开相应的对话框,得到结果,然后将该结果输入网格,替换现有值。问题是,属性Grid 似乎不允许访问其中的控件,所以我无法响应 OnClicked 事件。
以下是我希望喜欢代码的工作方式(编辑:更新代码):
private void propertyGrid_config_Click(object sender, EventArgs e)
{
PropertyGrid grid = (PropertyGrid)sender;
PropertyDescriptor selectedItem = grid.SelectedGridItem.PropertyDescriptor;
if (selectedItem.Category == "Files & Folders")
{
if (selectedItem.DisplayName.Contains("directory"))
{
FolderBrowserDialog folder = new FolderBrowserDialog();
if (folder.ShowDialog() == DialogResult.OK)
{
selectedItem.SetValue(grid.SelectedObject, folder.SelectedPath);
grid.Refresh();
}
}
else if (selectedItem.DisplayName.Contains("file"))
{
OpenFileDialog file = new OpenFileDialog();
if (file.ShowDialog() == DialogResult.OK)
{
selectedItem.SetValue(grid.SelectedObject, file.FileName);
grid.Refresh();
}
}
}
}
我已将网格的 "Clicked" 事件设置到此处理程序,但显然这不起作用,因为它只处理容器而不处理容器中的内容。 (请注意,如果我将它基于 "PropertyChanged" 事件,则此处理程序工作正常,但这显然不是我要找的。)
有什么方法可以访问组件并创建我想要的事件吗?你会如何解决这个问题?
如果相关,这里是 属性Grid 的一些代码:
网格存在于名为 "Configuration" 的 class 中,它定义了如下所有属性:
[Description("Folder for storing Bonding Key logs")]
[Category("Files & Folders")]
[DisplayName("Log output directory")]
public string dirLogOutput { get; set; }
XML 文件将有一个对应于每个 属性 的条目,如下所示:
<dirLogOutput>C:\Users\AHoffman\Desktop\TestData</dirLogOutput>
Serializer 可以很好地将 XML 文件中的数据匹配到网格,反之亦然:
public Configuration TryLoadConfiguration(Configuration thisConfig)
{
string filename = GetConfigFilename();
try
{
if (!File.Exists(filename))
{
thisConfig.setDefaults();
}
else
{
using (var stream = File.Open(filename, FileMode.Open, FileAccess.Read))
{
var serializer = new XmlSerializer(typeof(Configuration));
thisConfig = (Configuration)serializer.Deserialize(stream);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to load configuration file during startup: " + ex.Message);
thisConfig.setDefaults();
}
return thisConfig;
}
private void SaveConfiguration(string filename, Configuration thisConfig)
{
try
{
using (var stream = File.Open(filename, FileMode.Create, FileAccess.Write))
{
var serializer = new XmlSerializer(typeof(Configuration));
serializer.Serialize(stream, thisConfig);
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to save configuration file: " + ex.Message);
}
}
我注意到 here 之前有人问过这样的问题,但没有答案。希望我能给你足够的信息让你找回一些东西。
没关系。我找到了问题的答案 here (for files) and here(对于文件夹)。
这一切都依赖于为每种类型使用自定义 UITypeEditor
。
[EditorAttribute(typeof(OpenFileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
[EditorAttribute(typeof(FolderNameEditor2), typeof(System.Drawing.Design.UITypeEditor))]
非常感谢 @Simon Mourier, @Stewy, and @tzup 的回答。