Конференция "Компоненты" » Run time read only property [D5, D7, WinXP]
 
  • Deltas © (16.01.12 15:00) [0]
    Можно ли сделать свойство доступное только для чтения в run time, которое отображается и редактируется в инспекторе объектов? Зачем это нужно? Все необходимые изменения выполняются в методе TPropertyEditor.SetValue(const Value: string), поэтому запись свойства напрямую не нужна.
  • DimaBr © (16.01.12 15:08) [1]

    procedure SetValue()
    begin
       if not (ComponentState is csDesigning) then Exit;
    end;

  • Deltas © (16.01.12 15:16) [2]
    А если (csDesigning in ComponentState)? разве выполнится какой-то другой код? То есть это равносильно

    procedure SetValue()
    begin
    end;

    Хотелось бы, чтобы попытки записать свойство пресекались на уровне компиляции, то есть спецификатор write отсутствовал вообще, но тогда инспектор объектов не отображает свойство. Пока склоняюсь к варианту

    procedure SetValue();
    begin
     Assert(csDesiging in ComponentState);
    end;
  • icWasya © (16.01.12 15:34) [3]
    Ну тогда нужно иметь два pas-файла - один для сборки пакета с компонентами, другой - для использовании в проекте.
  • Омлет © (16.01.12 15:40) [4]
    Лучше пересмотреть архитектуру. Такое решение смахивает на костыли.
  • DimaBr © (16.01.12 16:03) [5]
    procedure SetValue()
    begin
       if not (ComponentState is csDesigning) then Exit;
      fValue = NewValue;
    // прочие действия
    end;

  • DimaBr © (16.01.12 16:06) [6]

    > Хотелось бы, чтобы попытки записать свойство пресекались на уровне компиляции, то есть спецификатор write отсутствовал вообще, но тогда инспектор объектов не отображает свойство.

    Тогда нужно писать свой редактор свойства, плюс само значение будет храниться не в PRIVATE иначе вы до него не достучитесь из редактора, значит в наследнике поле будет доступно
  • Deltas © (16.01.12 17:12) [7]

    > Омлет ©   (16.01.12 15:40) [4]
    > Лучше пересмотреть архитектуру. Такое решение смахивает
    > на костыли.


    Задача заключается в наделении экземпляров TDataSet именами (это не имя компонента).

    TNamedDataSet = class(TDataSet)
    private
     function GetDataSetName: string;
     procedure SetDataSetName(const Value: string);
    published
     property DataSetName: string read GetDataSetName write SetDataSetName;
    end;

    Необходимо, чтобы в режиме проектирования (хотя бы, т.к. в run time это не нужно) для компонента TDataSource можно было указать набор данных TDataSet. То есть:

    TDataSourceEx = class(TDataSource)
    private
     function GetDataSetName: string;
     procedure SetDataSetName(const Value: string);
    public
     property DataSetName: string read GetDataSetName write SetDataSetName;
    end;

    function TDataSourceEx.GetDataSetName: string;
    begin
     if DataSet is TNamedDataSet then
       Result := (DataSet as TNamedDataSet).DataSetName
     else
       Result := '';
    end;

    function TDataSourceEx.SetDataSetName(const Value: string);
    begin
     Assert(csDesigning in ComponentState);
    end;

    Зарегистрирован редактор свойства TDataSetNameProperty = class(TStringProperty), который при присвоении значения свойству редактируемого компонента ищет все экземпляры TNamedDataSet и по имени определяет экземпляр, после чего присваивает свойству DataSet ссылку на этот экземпляр. Логично было бы эту операцию выполнить в методе TDataSourceEx.SetDataSetName(const Value: string); но это усложняется тем, что базовый редактор свойства имеет свойства Designer, у которого есть метод GetComponentNames(), который ищет все нужные компоненты по всем модулям проекта. Данный метод не доступен в TDataSourceEx.SetDataSetName(const Value: string). Поэтому и такая реализация.
  • DimaBr © (16.01.12 17:33) [8]
    А для чего тогда свойство TDataSource.Dataset ???
  • DimaBr © (16.01.12 17:37) [9]
    Вы хотите менять имя Dataset, находясь в DataSource ?
  • Deltas © (16.01.12 18:32) [10]

    > DimaBr ©   (16.01.12 17:37) [9]
    > Вы хотите менять имя Dataset, находясь в DataSource ?


    Нет. Я хочу, чтобы свойство TDataSourceEx.DataSet изменилось автоматически, когда изменится свойство TDataSourceEx.DataSetName. При этом переменная TNamedDataSet.FDataSetName (private) не меняется.


    > DimaBr ©   (16.01.12 17:33) [8]
    > А для чего тогда свойство TDataSource.Dataset ???


    Конечный пользователь сам сможет указывать необходимый набор данных (TNamedDataSet) для источника данных (TDataSourceEx), при этом ему удобнее оперировать именем набора данных, а не именем компонента.
  • Deltas © (16.01.12 18:35) [11]
    P.S. TDataSourceEx не хранит имя TNamedDataSet, он лишь получает его, обращаясь к своему собственному свойству DataSet:

    function TDataSourceEx.GetDataSetName: string;
    begin
    if DataSet is TNamedDataSet then
      Result := (DataSet as TNamedDataSet).DataSetName
    else
      Result := '';
    end;

  • Deltas © (16.01.12 18:38) [12]
    То есть свойства DataSet и DataSetName должны работать синхронно: меняется одно - автоматически меняется второе, и наоборот.
  • DimaBr © (17.01.12 00:33) [13]
    Фактически вам нужен PropertyEditor для TDataSourceEx.DataSetName
  • icWasya © (17.01.12 09:45) [14]

    > DimaBr ©   (17.01.12 00:33) [13]
    > Фактически вам нужен PropertyEditor для TDataSourceEx.DataSetName

    Примерно такой, какой есть, например у TDBEdit для DataField.
 
Конференция "Компоненты" » Run time read only property [D5, D7, WinXP]
Есть новые Нет новых   [118241   +25][b:0][p:0.001]