我有一个带TabControl的用户界面,最初显示一个起始页面.可以通过双击(例如,DataGrid)中的内容将其他项添加到其中.创建新选项卡时应选择它们.如果与网格中的项目对应的文档已打开,则应打开该文档的现有选项卡,而不是创建新文档.
我知道我应该能够通过设置TabControl的SelectedItem或SelectedIndex属性以编程方式选择选项卡.但是,所需的选项卡实际上从未激活.如果我设置了一个,然后在调试器中检查TabControl的状态,那么两个字段似乎都正确更新.但是,在我继续执行之后,我看到选定的选项卡在UI中保持不变,如果我暂停并再次检查TabControl的状态,我会看到SelectedItem和SelectedIndex已经返回到之前的值.另一方面,通过在UI中单击选项卡来选择选项卡可以正常工作.
这是TabControl的声明:
<TabControl x:Name="Tabs" >
<TabItem x:Name="StartPageTab" Header="Start Page" DataContext="{Binding Path=StartPageViewModel}">
...
</TabItem>
</TabControl>
Run Code Online (Sandbox Code Playgroud)
以及添加和选择标签的代码:
private void _SelectTab(MyViewModel model)
{
TabItem tab;
if (_TryFindTab(model, out tab)) Tabs.SelectedItem = tab;
}
private bool _TryFindTab(MyViewModel target, out TabItem tab)
{
foreach (TabItem item in Tabs.Items)
{
MyViewModel model = item.DataContext as MyViewModel;
if (model != null && model.Equals(target))
{
tab = item;
return true;
}
}
tab = null;
return false;
}
private void _AddTab(MyViewModel model)
{
TabItem tab = new …Run Code Online (Sandbox Code Playgroud) 我有一个需要提供规范化字符串的例程.但是,进入的数据不一定是干净的,如果字符串包含无效的代码点,String.Normalize()会引发ArgumentException.
我想做的只是用一个一次性字符替换那些代码点,例如'?'.但要做到这一点,我需要一种有效的方法来搜索字符串,以便首先找到它们.有什么好办法呢?
以下代码有效,但它基本上使用try/catch作为粗略的if语句,因此性能很糟糕.我只是分享它来说明我正在寻找的行为:
private static string ReplaceInvalidCodePoints(string aString, string replacement)
{
var builder = new StringBuilder(aString.Length);
var enumerator = StringInfo.GetTextElementEnumerator(aString);
while (enumerator.MoveNext())
{
string nextElement;
try { nextElement = enumerator.GetTextElement().Normalize(); }
catch (ArgumentException) { nextElement = replacement; }
builder.Append(nextElement);
}
return builder.ToString();
}
Run Code Online (Sandbox Code Playgroud)
(编辑:)我正在考虑将文本转换为UTF-32,以便我可以快速迭代它,看看每个dword是否对应一个有效的代码点.有没有这样做的功能?如果没有,是否有一个无效范围列表在那里漂浮?
我正在使用一个表单,可以通过编程方式创建和删除一些ComboBox.
创建它们时,会创建一些以它们为目标的触发器并将其应用于按钮:
Dictionary<ComboBox, DataTrigger> triggers = new Dictionary<ComboBox, DataTrigger>();
private void CreateTrigger(ComboBox box)
{
Style s = new Style(typeof(Button), MyButton.Style);
foreach(TriggerBase aTrigger in MyButton.Style.Triggers)
s.Triggers.Add(aTrigger);
DataTrigger t = new DataTrigger
{
Binding = new Binding("SelectedItem") { Source = box },
Value = null
};
t.Setters.Add(new Setter(Button.IsEnabledProperty, false));
s.Triggers.Add(t);
triggers.Add(box, t);
MyButton.Style = s;
}
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好*...问题是,从窗口中删除ComboBox时该怎么办.我需要从按钮的Style中删除触发器,因为我不再希望ComboBox影响它的行为.我尝试了最明显的选择:
private void RemoveTrigger(ComboBox box)
{
Style s = new Style(typeof(Button), MyButton.Style);
foreach(TriggerBase aTrigger in MyButton.Style)
if(aTrigger != triggers[box]) s.Triggers.Add(aTrigger);
triggers.Remove(box);
MyButton.Style = s;
}
Run Code Online (Sandbox Code Playgroud)
但这似乎不起作用 …
我知道(并同意)将单元测试放在单独的程序集中的常用参数.但是,最近我遇到了一些我真的想要测试私有方法的情况.有问题的幕后逻辑足够复杂,以至于测试公共和内部接口并不能完成任务.对班级公共界面的测试感觉过于紧张,我看到几个地方,对私人的一些测试可以更简单有效地完成工作.
在过去,我通过制作我需要测试的东西来解决这些情况protected,并创建一个我可以用来在测试框架中获取它的子类.但是,这并不在类,应该是工作这么好sealed.更不用说用所有脚手架膨胀测试框架.
所以我正在考虑这样做:在课堂上放置一些测试,他们可以在那里找到私人成员.但是使用'#if DEBUG`将它们排除在生产代码之外.
这看起来是个好主意吗?
我试图弄清楚如何最好地查询由一个中央表以及记录一对多关系的多个“属性”表(抱歉,这里不确定最好的术语)组成的架构。在业务层中,这些表中的每一个对应于一个可能包含零个或多个元素的集合。
现在,我正在查看的代码通过从主表中获取值列表来检索数据,然后对其进行循环并查询每个“附件”表以填充这些集合。
如果可以的话,我想尝试将其简化为单个查询。我尝试使用多个LEFT JOIN。但这有效地连接了附件表中值的叉积,从而导致行激增-尤其是当您添加更多连接时。该表包括五个此类关系,因此每个记录返回的行数可能很大,并且几乎完全由冗余数据组成。
这是一些表,数据,我正在使用的查询结构和结果的较小综合示例:
数据库结构和数据:
create table Containers (
Id int not null primary key,
Name nvarchar(8) not null);
create table Containers_Animals (
Container int not null references Containers(Id),
Animal nvarchar(8) not null,
primary key (Container, Animal)
);
create table Containers_Foods (
Container int not null references Containers(Id),
Food nvarchar(8) not null,
primary key (Container, Food)
);
insert into Containers (Id, Name)
values (0, 'box'), (1, 'sack'), (2, 'bucket');
insert into Containers_Animals (Container, Animal)
values (1, 'monkey'), …Run Code Online (Sandbox Code Playgroud) 我遇到过一种情况,根据minidump,某些文件在递归下降解析器中导致堆栈溢出.不幸的是我不能让我的手,这是否为了重现该问题(客户有保密性问题),这让我有点砍断诊断上真正的问题一时还文件的例子.
很明显,解析器需要一些关注,但现在我的首要任务是保持程序运行.作为权宜之计,我该怎样做才能阻止整个计划的落实?
我的第一选择是找到某种方法来预测我在堆栈上的空间不足以便我可以在溢出发生之前优雅地中止解析器.无法解析文件是可以接受的选项.第二种选择是让它发生,捕获错误并记录它,然后继续其余的数据.
解析发生在Parallel.ForEach()循环中.如果有帮助,我愿意将其换成其他方法.
编辑: 如果我能够获得当前线程堆栈的大小以及堆栈指针的位置,那么真正的杀手是什么.这可能吗?
编辑2: 我终于设法从某人那里取出一个样本文件并将错误记录在调试器中.事实证明,它根本不属于我们的代码 - HtmlAgilityPack中的某个地方发生了异常.所以看起来我将不得不尝试找到一个完全不同的方法.
我正在考虑按照“一次性”设计模式创建一些类,由以下功能定义:
execute方法两次将引发异常。execute调用方法之前修改属性。之后调用它们也会引发异常。极简主义的实现可能如下所示:
public class Worker
{
private bool _executed = false;
private object _someProperty;
public object SomeProperty
{
get { return _someProperty; }
set
{
ThrowIfExecuted();
_someProperty = value;
}
}
public void Execute()
{
ThrowIfExecuted();
_executed = true;
// do work. . .
}
private void CheckNotExcecuted()
{
if(_executed) throw new InvalidOperationException();
}
}
Run Code Online (Sandbox Code Playgroud)
问题:
我正在使用Windsor Logging Facility和NLog集成向项目添加日志记录.
而不是遵循Windsor文档建议的向Log每个我想支持日志记录的类添加属性的做法,我决定尝试使用动态拦截来实现它.到目前为止,拦截器相当基本; 它只是使用构造函数注入来获取一个实例ILogger:
class LoggingInterceptor : IInterceptor
{
private readonly ILogger _logger;
public LoggingInterceptor(ILogger logger)
{
if (logger == null) throw new ArgumentNullException("logger");
_logger = logger;
}
public void Intercept(IInvocation invocation)
{
// just a placeholder implementation, I'm not actually planning to do this ;)
_logger.Info(invocation.Method.Name);
invocation.Proceed();
}
}
Run Code Online (Sandbox Code Playgroud)
除此之外,我所做的只是注册拦截器并将其应用于组件的最小值,而日志工具则负责其余部分.
container.Register(Component.For<LoggingInterceptor>().LifeStyle.Transient);
container.Register(
Component.For<IEmployeeRepository>()
.ImplementedBy<EmployeeRepository>()
.Interceptors(InterceptorReference.ForType<LoggingInterceptor>()).First);
Run Code Online (Sandbox Code Playgroud)
到目前为止这么好 - 有点像.我得到的记录器遵循NLog推荐的每个类一个记录器的做法.在这种情况下,我认为这不是一个很好的选择.这意味着每条消息都会转到一个名为"MyApplication.Interceptors.LoggingInterceptor"的日志,这个日志并不是非常有用.
我更喜欢在已经应用了记录器的抽象之后命名日志.例如,如果已将记录器应用于实现,IEmployeeRepository则应该命名日志EmployeeRepository.这可行吗?
编辑:
我已经尝试实现自定义ILoggerFactory并指示容器使用它.然而,我很快遇到了障碍:当Windsor进入工厂时,提供的唯一信息是获取记录器的对象类型.没有提供有关该对象的其他信息,因此ILoggerFactory无法找到拦截器已应用的抽象.
我注意到有两个重载ILoggerFactory.Create()接受字符串作为参数.温莎似乎没有直接使用其中任何一个,但人们会认为他们必须在那里是有原因的.流畅的注册API中是否有可用于指定使用特定字符串的内容?
我正在进行需要调用更多异步任务的异步操作.我试图通过使用BackgroundWorkers来保持简单,结果是一个BackgroundWorker的DoWork()回调调用一个创建第二个BackgroundWorker的方法,就像这样(减去错误检查和所有爵士乐的简洁):
class Class1
{
private BackgroundWorker _worker = null;
public void DoSomethingAsync()
{
_worker = new BackgroundWorker();
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
_worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
_worker.RunWorkerAsync();
}
void _worker_DoWork(object sender, DoWorkEventArgs e)
{
Class2 foo = new Class2();
foo.DoSomethingElseAsync();
while(foo.IsBusy) Thread.Sleep(0); // try to wait for foo to finish.
}
void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// do stuff
}
}
class Class2
{
private BackgroundWorker _worker = null;
Thread _originalThread = null;
public AsyncCompletedEventHandler DoSomethingCompleted;
public bool IsBusy { …Run Code Online (Sandbox Code Playgroud) 我正在研究使用AesCryptoServiceProvider解密二进制数据的过程.对于最后一步,检索解密数据并将其作为字节数组返回,我目前正在使用以下实现:
let rec streamBytes (s : CryptoStream) (b : int) = seq {
if b >= 0 then
yield byte b
yield! streamBytes s (s.ReadByte()) }
streamBytes cryptoStream (cryptoStream.ReadByte())
|> Seq.toArray
Run Code Online (Sandbox Code Playgroud)
它有效,但它对我来说并不"正确".将CryptoStream.ReadByte()的结果作为参数传递给streamBytes(),然后检查该递归调用中的值似乎有点Rube Goldberg-y.有更好的方法吗?
我正在实现一个持久集合 - 为了论证,让我们说它是一个单链表,是函数式语言中常见的样式.
class MyList<T>
{
public T Head { get; }
public MyList<T> Tail { get; }
// other various stuff
// . . .
}
Run Code Online (Sandbox Code Playgroud)
拥有这个类实现似乎很自然ICollection<T>,因为它可以实现所期望的所有正常行为ICollection<T>,至少在广泛的行程中.但是这个阶级的行为和行为之间存在很多不匹配ICollection<T>.例如,Add()方法的签名
void Add(T item); // ICollection<T> version
Run Code Online (Sandbox Code Playgroud)
假设添加将作为改变集合的副作用执行.但这是一个持久的数据结构,因此Add()应该创建一个新的列表并返回它.
MyList<T> Add(T item); // what we really want
Run Code Online (Sandbox Code Playgroud)
解决此问题的最佳方法似乎是创建我们想要的版本,并生成接口中定义的版本的非功能性显式实现.
void ICollection<T>.Add(T item) { throw new NotSupportedException(); }
public MyList<T> Add(T item) { return new MyList<T>(item, this); }
Run Code Online (Sandbox Code Playgroud)
但我对这个选项有一些担忧:
这会让用户感到困惑吗?我设想有人正在使用这个类的场景,并发现在它上面调用Add()有时会引发异常,有时会运行但不会像ICollection通常预期的那样修改列表,具体取决于相关的类型信息使用参考?
继(1)之后,ICollection<T>s 的实现IsReadOnly应该可以归结为真.但这似乎与Add()与类实例一起使用的其他点隐含的内容相冲突.
是否(2)通过再次遵循显式实现模式以非混淆的方式解决,新版本返回false …
我想找出使用最少量样板代码执行数据库查询的最佳方法.SqlCommand文档中建议的方法:
private static void ReadOrderData(string connectionString)
{
string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1]));
}
}
finally
{
reader.Close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
主要包括必须在与数据库交互的每个方法中重复的代码.
我已经习惯于分解连接的建立,这将产生更像下面的代码.(我也在修改它以便它返回数据,以使示例变得不那么简单.)
private SQLConnection CreateConnection()
{
var connection = new SqlConnection(_connectionString);
connection.Open();
return connection;
}
private List<int> ReadOrderData()
{
using(var connection = CreateConnection())
using(var command = connection.CreateCommand())
{ …Run Code Online (Sandbox Code Playgroud) 我正在尝试修改一些现有代码,以使用Castle Windsor作为IoC容器.
有问题的应用程序是面向文档的.因此,它有一个对象图,它依赖于指定在注册时无法知道的数据源的数据,并且每次解析对象图时都会更改.但是,这种依赖是对象图中的几个层,因此我不能仅将其作为参数传递,container.Resolve()因为Windsor不传播内联依赖项.
我提出的解决方案是使用类型化工厂工具生成一个工厂,它可以解析图中的每个依赖项,并且Document构造函数接受此工厂的实例以及指定数据源的字符串.工厂在注册时指定,数据源在解决时指定.构造函数从那里接管,手动轮询工厂以解决依赖关系.结果看起来像这样:
public interface IDataSource { /* . . . */ }
public interface IWidgetRepository { /* . . . */ }
public interface IWhatsitRepository { /* . . . */ }
// Implementation generated by Windsor's typed factory facility
public interface IFactory
{
IDataSource CreateDataSource(string path);
IWidgetRepository CreateWidgetRepository(IDataSource dataSource);
IWhatsitRepository CreateWhatsitRepository(IDataSource dataSource);
void Release(IDataSource dataSource);
void Release(IWidgetRepository widgetRepository);
void Release(IWhatsitRepository whatsitRepository);
}
public class Document
{
private readonly IDataSource _dataSource;
private readonly IWidgetRepository …Run Code Online (Sandbox Code Playgroud) c# dependency-injection castle-windsor typed-factory-facility
c# ×11
.net ×3
sql-server ×2
wpf ×2
ado.net ×1
collections ×1
f# ×1
nlog ×1
oop ×1
sql ×1
stream ×1
t-sql ×1
tabcontrol ×1
unicode ×1
unit-testing ×1