Почему привязка TextBox не работает правильно в первом примере?
Это потому, что TypeDescriptor
из DataRow
не имеет свойства Id
. Рассмотрим следующие правила:
Когда привязка данных к свойству элемента, дескриптор типа элемента должен содержать свойство с таким именем.
При привязке данных к списку дескриптор типа элемента списка должен содержать свойство с таким именем.
Верно ли говорить, что автоматическое (без какого-либо дополнительного вызова для связывания do) распространение из источника в управление происходит только с DataRow?
Нет. Это не из-за типа DataRow
. Это из-за INotifyPropertyChanged
и IBindingList
. Рассмотрим следующие правила:
Когда данные связывают элемент управления с элементом, если элемент реализует INotifyPropertyChanged
, пользовательский интерфейс будет обновляться сразу после обновления элемента.
При привязке данных к элементу управления списком, если элемент реализует INotifyPropertyChanged
и список реализует IBindingList
, пользовательский интерфейс будет обновляться сразу после обновления элемента или списка.
Дополнительная информация
Коротко о том, что я описал выше, вы можете найти в Привязка данных Windows Forms . Я рекомендую прочитать следующие полезные документы:
Необходимо обеспечить больше данных.
Обратите внимание, что через OnTerminate называют, Синхронизируются, который требует вызова к CheckSynchronize в какой-то момент где-нибудь. Приложение. ProcessMessages обычно делает это, но в зависимости от того, как VCL был инициализирован, возможно, что Синхронизировать механизм не был полностью сцеплен вместе в консольном приложении.
В любом случае эта программа работает как ожидалось над моей машиной:
uses Windows, SysUtils, Classes, Forms;
var
threadCount: Integer;
type
TMyThread = class(TThread)
public
procedure Execute; override;
class procedure Go;
class procedure HandleOnTerminate(Sender: TObject);
end;
procedure TMyThread.Execute;
begin
end;
class procedure TMyThread.Go;
function MakeThread: TThread;
begin
Result := TMyThread.Create(True);
Inc(threadCount);
Result.OnTerminate := HandleOnTerminate;
end;
var
t1, t2, t3: TThread;
begin
t1 := MakeThread;
t2 := MakeThread;
t3 := MakeThread;
t1.Resume;
t2.Resume;
t3.Resume;
while threadCount > 0 do
Application.ProcessMessages;
end;
class procedure TMyThread.HandleOnTerminate(Sender: TObject);
begin
InterlockedDecrement(threadCount);
end;
begin
try
TMyThread.Go;
except
on e: Exception do
Writeln(e.Message);
end;
end.
Как Barry справедливо указал, если CheckSyncronize не называют, Синхронизируйтесь, не назван, и если синхронизируются, не назван, то событие OnTerminate не запущено. То, что, кажется, происходит, - то, что, когда я выполняю свои Модульные тесты как консольное приложение, нет никаких сообщений на очереди сообщений и таким образом Приложения. ProcessMessage, который называют от Processmessages, никогда не добирается для вызова checkSynchronize. Я теперь решил проблему путем изменения цикла на
While fThreadRefCount > 0 do
begin
Application.ProcessMessages;
CheckSynchronize;
end;
Это теперь работает и в консоли и в gui режимах.
Целый рычаг wakeupmainthread, кажется, установка правильно. Именно этот рычаг добавляет сообщение WM_NULL, которое инициировало checksynchronize. Это просто не получает это далеко в консольном приложении.
Больше расследования
Поэтому Синхронизируйтесь, действительно становится названным. Вызовы DoTerminate Синхронизируются (CallOnTerminate), но там существует строка:
WaitForSingleObject(SyncProcPtr.Signal, Infinite);
который просто ожидает навсегда.
Таким образом, в то время как моя фиксация выше работ, существует что-то глубже к этому!