我正在通过一个名为Revit的架构建模软件的API创建一个自定义加载项命令.我的命令可能需要一些时间才能完成,因此我想向用户显示一个带有进度条的窗口,因为它正在工作.
通常,如果我要创建这样的进度窗口,它将位于主UI线程上,并且正在完成的实际工作将在辅助工作线程上进行.但是,Revit要求对API的任何访问都是通过调用自定义命令的线程进行的.所以我必须在第二个线程上创建我的进度条.
我发现这篇博客文章是关于在一个单独的线程中启动WPF窗口,并基于我的解决方案.这是我的自定义命令类.
public class SampleProgressWindowCommand : Autodesk.Revit.UI.IExternalCommand
{
private ProgressWindow progWindow;
internal static EventWaitHandle _progressWindowWaitHandle;
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
//Starts New Progress Window Thread
using (_progressWindowWaitHandle = new AutoResetEvent(false))
{
//Starts the progress window thread
Thread newprogWindowThread = new Thread(new ThreadStart(ShowProgWindow));
newprogWindowThread.SetApartmentState(ApartmentState.STA);
newprogWindowThread.IsBackground = true;
newprogWindowThread.Start();
//Wait for thread to notify that it has created the window
_progressWindowWaitHandle.WaitOne();
}
//Does some work that takes a long time
for (int i = …Run Code Online (Sandbox Code Playgroud) 我试图找出保存(序列化)和以后打开(反序列化)树结构的最佳方法.我的结构由具有不同属性的各种对象类型组成,但每个都继承自基本抽象"Node"类.
每个节点都有唯一的ID(GUID),并有一个AddSuperNode(Node nd)方法,用于设置节点的父节点.这反过来调用其他方法,允许父节点知道它具有哪些子节点.但是,某些节点还使用AddAuxSuperNode()方法向节点添加辅助父节点.
我正在使用二进制序列化,但现在我想我想使用一些我有更多控制的东西,并且序列化数据更容易访问.我还希望在反序列化时保留Type信息,并能够序列化私有值.所以DataContractSerializer似乎是最好的方式.
我不能只序列化的根节点直接因为有多个父节点.我不想创建重复的对象.所以我似乎需要将树解构为一个平面列表,然后将其序列化.然后在序列化该列表后重建树.这听起来不错吗?
就像我之前说的,每个节点都有一个唯一的GUID标识符,但是现在节点直接引用它们的父节点/子节点而不存储它们的id.我可以更新AddSuperNode()和AddAuxSuperNode()方法,以便除了直接引用之外还更新要序列化的父ID列表.但是我宁愿只在序列化对象时更新/创建这个列表.所以我想在节点中创建一个UpdateSuperNodeIDRefs()方法,该方法将在序列化之前调用.
以下是我计划对此结构进行序列化和反序列化的操作.任何人都可以建议更好/更清洁/更有效的方法吗?
序列化
1)提供树结构的根节点
2)细分树结构成扁平字典(GUID ID,节点ND)其中ID是GUID的ND.
3)调用UpdateSuperNodeIDRefs() ; 为每个节点更新为其父节点保存的ID.
4)使用DataContractSerializer序列化节点字典
反序列化
1)反序列化节点字典
2)遍历字典中的每个节点,将每个节点重新连接到其父节点.对于存储的任何父ID,查找具有匹配ID 的字典中的相应节点调用AddSuperNode()或AddAuxSuperNode()以将节点重新连接到其父节点.
3)从Dictionary中的任何节点找到结构的根
4)返回根节点
我正在使用PropertyGrid来显示我的对象的属性.但是,我还允许用户创建自己的属性,并为这些自定义属性设置值.每个可以拥有这些自定义属性的对象都有一个Dictionary集合,其中字符串是标识属性的唯一键,Object是基本类型的值(string,bool,int等...)
我创建了一个自定义PropertyDescriptor,其中包含get和set方法,用于检查Dictionary以查找匹配的键,或者分别使用匹配的键创建/覆盖该值.
但是,我还希望让用户能够清除属性,从而完全从字典中删除其条目.我将代码放在我的自定义PropertyDescriptor的ResetValue覆盖方法中,但是我没有看到任何通过PropertyGrid接口来调用它的方法?它似乎不是一个上下文菜单选项或类似的东西.
因此,如果我有一个带有自定义ResetValue方法的自定义PropertyDescriptor,我如何从PropertyGrid中实际唤起该方法?
是否有更好的方法要求方法中的参数不为null?我一直在检查我的方法所需的任何参数是否为null,如下所示。但是我想知道是否有更好的方法。
public void MyMethod(string a, int b)
{
if(a==null){throw new ArgumentNullException("a");}
if(b==null){throw new ArgumentNullException("b");}
//more stuff here
}
Run Code Online (Sandbox Code Playgroud) 使用a PropertyDescriptor返回IsReadOnly()方法的值和与ReadOnlyAttribute?相关的值有什么区别?
我正在使用System.Windows.Forms.DataGrid.它填充了大约3000行并且重绘速度非常慢.如果我最小化和最大化我的表单所有其他控件只显示但我最终逐行观看DataGrid重绘.如果这会产生影响,那么此DataGrid中的所有内容都是只读的.
更新:
我不确定如何为我的项目正确实现CellValueNeeded()事件,或者它是否有助于我的DataGrid的性能.
我正在创建一个包含DataGridView的用户控件(请参阅下面的代码).调用SetProject()方法时,我的控件被设置为我的Project类的特定实例.然后控件使用静态方法Informa.Data.GetProjectDataTable(Project proj)从Project中提取DataTable.然后将DataGrid的DataSource属性设置为返回的DataTable.
这是我第一次使用ADO或DataGrids做任何事情,所以请耐心等待.看起来CellValueNeed()允许我覆盖DataGrid如何为其中一个单元格找到值,但在我的情况下,这比MSDN上的示例复杂得多.我的数据的实际来源是各种Node对象的树结构,其根目录是Project实例.每个节点都可以有一组可变属性,用户也可以在运行时进行扩展.然后还有许多其他复杂性,节点从其父节点继承属性值,并从其子节点总计其他属性.
Informa.Data.GetProjectDataTable()切断所有这些疯狂,并生成所有节点的所有属性的单个平面DataTable.此时,我不关心是否能够将此表的任何更改与原始树结构相关联,或者在树结构更改时更新表的特定部分.我想要做的就是在DataGrid中向用户显示数据.
那么我实现CellValueNeeded()来从Project提供的DataTable中读取吗?我认为DataGrid已经知道如何有效地使用DataTable作为DataSource?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Informa;
namespace Informa
{
public partial class ProjectGridControl : UserControl
{
private Project proj;
public ProjectGridControl()
{
InitializeComponent();
}
public void SetProject(Project proj)
{
this.proj = proj;
UpdateGridControl();
}
public void UpdateGridControl()
{
if (this.proj == null)
{
this.dataGrid.DataSource = null;
}
else
{
//Extracts a DataTable from the project and sets it as the …Run Code Online (Sandbox Code Playgroud) 所以我的构造函数中有一个带有单个字符串参数的类:
public MyClass(string name)
{
this.Name = name;
}
Run Code Online (Sandbox Code Playgroud)
但我永远不想担心有人初始化一个名为NULL或零长度字符串的MyClass实例.什么是最好的验证参数?使用属性或方法,如果提供了无效参数,您可以随时执行任何操作,返回null或不设置任何内容.但是一旦调用了构造函数,就会创建该对象的实例,无论它是否传递了有效的参数.
如下所示抛出异常最好的方法?或者是否有其他更优选的方法?
public MyClass(string name)
{
if (name == null | name == "") throw new ArgumentException("Name can not be null or blank", "name");
this.Name = name;
}
Run Code Online (Sandbox Code Playgroud)
当然,如果参数无效,我总是可以将名称设置为某些默认名称,如"Unnamed MyClass",但在这种情况下,我宁愿只是阻止一个无效的名称,然后尝试假设一些替代行为.
我正在编写一个使用树结构的应用程序,所以当然我有一些递归方法会迭代树的每个节点并做一些事情.问题是有时这些需要一段时间,而我宁愿向用户显示某种进度条,而不是程序停止响应一段时间.
如果我在一个平面列表中进行迭代,我知道列表中有多少项是开始的,因此很容易跟踪循环所在的数字并相应地更新进度条.
但是,通过迭代树结构的递归方法,我不一定知道树在开始时有多少个节点.我应该首先递归地读取树并在运行实际的递归方法之前计算所有节点,这样做我想做什么吗?或者可能只是在树中添加或删除节点时跟踪运行总计?有更好的选择吗?
我正在编写一个简单的程序,用于将文件同步到FTP.我希望能够检查文件的本地版本是否与远程版本不同,因此我可以判断文件是否需要传输.我可以检查文件大小,但这不是100%可靠,因为显然两个文件可能大小相同但包含不同的数据.修改文件的日期/时间也不可靠,因为用户的计算机日期可能设置错误.
有没有其他方法来判断FTP上的本地文件和文件是否相同?
我正在创建一个基于AbstractNode类的树结构。该是AbstractNode类具有包含其子节点的通用集合属性。请参阅下面的代码示例。
有没有办法,可能使用泛型,我可以限制AbstractNode的具体版本只允许一种类型的子节点?请参阅下面的ConcreteNodeA代码,其中的 ChildNodes 属性是ConcreteNodeB而不是AbstractNode的集合。这当然不能编译,但我想知道是否有其他方法可以用来达到同样的效果。
当然,一切都将与ChildNodes集合属性一起工作,该属性始终为AbstractNode类型,但我试图将一些逻辑嵌入到我的类中,以了解哪些节点应该是其他节点的子节点。另外,在引用ChildNodes属性时,如果我不必将集合转换为我知道它应该是的类型的集合,那就太好了。
public abstract class AbstractNode
{
public abstract NodeCollection<AbstractNode> ChildNodes
{
get;
set;
}
}
public class ConcreteNodeA : AbstractNode
{
//THIS DOES NOT COMPLILE
//Error 1 'ConcreteNodeA.ChildNodes': type must be 'NodeCollection<AbstractNode>'
//to match overridden member 'AbstractNode.ChildNodes'
public override NodeCollection<ConcreteNodeB> ChildNodes
{
get;
set;
}
}
public class ConcreteNodeB : AbstractNode
{
public override NodeCollection<AbstractNode> ChildNodes
{
get; …Run Code Online (Sandbox Code Playgroud) c# ×9
tree ×2
.net ×1
arguments ×1
attributes ×1
constructor ×1
datacontract ×1
datagrid ×1
file ×1
ftp ×1
generics ×1
methods ×1
null ×1
propertygrid ×1
readonly ×1
recursion ×1
revit-api ×1
validation ×1
winforms ×1
wpf ×1