Если Вы отключаете панель, al средства управления на нем отключены также.
Рекурсивное решение с анонимными методами:
type
TControlProc = reference to procedure (const AControl: TControl);
procedure TForm6.ModifyControl(const AControl: TControl;
const ARef: TControlProc);
var
i : Integer;
begin
if AControl=nil then
Exit;
if AControl is TWinControl then begin
for i := 0 to TWinControl(AControl).ControlCount-1 do
ModifyControl(TWinControl(AControl).Controls[i], ARef);
end;
ARef(AControl);
end;
procedure TForm6.Button1Click(Sender: TObject);
begin
ModifyControl(Panel1,
procedure (const AControl: TControl)
begin
AControl.Enabled := not Panel1.Enabled;
end
);
end;
Я использую поток BackgroundProcess, чтобы делать такие вещи.
Вот ссылка на MSDN по этому поводу: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Дополнительная информация по этому поводу.
Вы иметь три СОБЫТИЯ, связанных с вашим объектом BackgroundProcess: DoWork, ReportProgress и WorkCompleted.
Теперь, чтобы использовать это - и использовать его с наблюдаемой коллекцией - вы захотите сообщить объекту BackgroundProcess, чтобы он мог ОТЧЕТАТЬ О ПРОГРЕССЕ ( это логическое свойство, которое я всегда явно устанавливаю вместе с разрешающей отменой).
Теперь, чтобы начать процесс, вы вызовете метод RunWorkerAsync. Этот метод имеет возможность принимать переменную OBJECT в случае, если вам нужно передать ей данные (если вы хотите более 1 значения, создайте структуру для передачи в RunWorkerAsync).
RunWorkerAsync запускает событие DoWork, поэтому управление переходит к обработчику событий DoWork. Вот (очищенный) код, из которого я его использую:
Dim dt As System.Data.DataTable
dt = da.GetDataTable(sql, System.Data.CommandType.Text, params)
For Each row As System.Data.DataRow In dt.Rows
If loadQuestionsWorker.CancellationPending Then
e.Cancel = True
Exit Sub
End If
Dim item As New DataObject
// Assign Item Values
backgroundProcessObject.ReportProgress(1, item)
Next
Здесь происходит то, что я получаю данные из моего уровня данных, а затем, пока этот фоновый процесс не отменяется, я иду по таблице данных , и когда я создаю новый DataObject, я сообщаю, что этот объект создается.
Теперь в моем обработчике событий ProgressChanged (метод ReportProgress вызывает событие ProgressChanged) элемент управления снова в руках потока пользовательского интерфейса, поэтому я могу делать такие вещи, как повлиять на пользовательский интерфейс и добавить элемент, о котором я сообщаю, в ObservableCollection.
Вы можете явно запустить новый поток
или BackgroundWorker
, либо использовать ThreadPool
. Я не знаю ни одного рекомендуемого способа сделать это в MVVM ...
Если ваша асинхронная операция заполняет ObservableCollection, привязанную к элементу управления, обратите внимание, что вы не можете добавлять элементы к нему в другом потоке. Это нужно сделать в потоке диспетчера элемента управления. Или вы также можете использовать эту коллекцию , которая вызывает событие CollectionChanged в соответствующем потоке
var t = new Thread((ThreadStart)delegate
{
DoWork(...)
Dispatcher.BeginInvoke((Action)delegate
{
SomethingOntheUiThread(...)
FinishedWork(...);
}
});
t.Start();