Я не думаю, что это может быть сделано с единственным регулярным выражением. И границы могут или не могут работать в зависимости от того, против чего Вы соответствуете.
я соответствовал бы против каждого regex отдельно и сделал бы XOR на результатах.
foo = re.search("foo", str) != None
bar = re.search("bar", str) != None
if foo ^ bar:
# do someting...
Вы можете расширить BindingList, чтобы использовать ISynchronizeInvoke (реализованный System.Windows.Forms.Control) для маршалинга вызовов событий в поток пользовательского интерфейса.
Затем все, что вам нужно сделать, это использовать новый тип списка, и все отсортировано.
public partial class Form1 : System.Windows.Forms.Form {
SyncList<object> _List;
public Form1() {
InitializeComponent();
_List = new SyncList<object>(this);
}
}
public class SyncList<T> : System.ComponentModel.BindingList<T> {
private System.ComponentModel.ISynchronizeInvoke _SyncObject;
private System.Action<System.ComponentModel.ListChangedEventArgs> _FireEventAction;
public SyncList() : this(null) {
}
public SyncList(System.ComponentModel.ISynchronizeInvoke syncObject) {
_SyncObject = syncObject;
_FireEventAction = FireEvent;
}
protected override void OnListChanged(System.ComponentModel.ListChangedEventArgs args) {
if(_SyncObject == null) {
FireEvent(args);
}
else {
_SyncObject.Invoke(_FireEventAction, new object[] {args});
}
}
private void FireEvent(System.ComponentModel.ListChangedEventArgs args) {
base.OnListChanged(args);
}
}
Это мнение вполне справедливо. Под покровом другие объекты, такие как CurrencyManager и Binding, обеспечивают обновление элементов управления при изменении базового источника данных.
Добавление элемента в привязанный к данным BindingList запускает серию событий, которые в конечном итоге приводят к попытке обновления DataGridView. Поскольку пользовательский интерфейс может быть обновлен только из потока пользовательского интерфейса, вам следует добавлять элементы в BindingList из потока пользовательского интерфейса через Control.Invoke .
Я собрал быстрый пример создания формы с помощью DataGridView, BindingSource и Button.
Кнопка запускает другой поток, который имитирует получение нового элемента для включения в BindingList.
Само включение выполняется обратно в поток пользовательского интерфейса через Control.Invoke.
public partial class BindingListChangedForm : Form {
BindingList<Person> people = new BindingList<Person>();
Action<Person> personAdder;
public BindingListChangedForm() {
InitializeComponent();
this.dataGridView1.AutoGenerateColumns = true;
this.bindingSource1.DataSource = this.people;
this.personAdder = this.PersonAdder;
}
private void button1_Click(object sender, EventArgs e) {
Thread t = new Thread(this.GotANewPersononBackgroundThread);
t.Start();
}
// runs on the background thread.
private void GotANewPersononBackgroundThread() {
Person person = new Person { Id = 1, Name = "Foo" };
//Invokes the delegate on the UI thread.
this.Invoke(this.personAdder, person);
}
//Called on the UI thread.
void PersonAdder(Person person) {
this.people.Add(person);
}
}
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}