Şu konuda basit bir yöntem bulamadım.
Evet-Hayır, Aktif-Pasif vb. bilgileri LookupCombobox ile gösteriyorum. Tablodaki değerleri 0-1, görünen değerleri Hayır-Evet gibi bir yapı var.
Bu kısa datalar için tablo yapıyorum. Ancak aynı tablo içinde, veya aynı form içinde birden çok bu şekilde (Evet-Hayır) yapısını kullanmam gereken alan var. ClientDataSet kullandığımda da aynı problem var.
Bu tip kısa dataları, nesneler üzerinde nasıl pratik bir şekilde kullanabilirim? Özellikle de aynı yapıyı bir çok yerde kullanmam gerekiyorsa?
Her bir lookupcombobox alanı için kendim değerler girebiliyor olsam benim için çok pratik olacak.
Databaseden gelen veriler kullanıcıya gösterilmeden önce manüple edebiliyorsunuz.
Aynı şekilde kullanıcının seçimini database yazmadan önce yine bu noktada manüple edebiliyorsunuz.
Diğer bir ifade şekli ile databaseden 0,1,2 şeklinde gelen değerleri Evet, Hayır, Belki gibi kullanıcıya (combobox vb. içerisinde) gösterebilirsiniz.
Kullanıcının seçimini tekrar databaseye yazarken 0,1,2 şeklinde yazılmasını sağlayabilirsiniz.
0,1,2 (evet, hayır, belki) örneğindeki gibi bir yapı farklı farklı form ve nesnelerde ortak kullanılıyorsa, bu eventleri (getText ve SetText) aynı yere bağlayabilirsiniz. Örneğin artık "Evet" ler "Tamam" şeklinde görünmesi istendiğinde, sadece yukarıdaki iki eventde değişiklik yapmanız yeterli olur.
Uygulanabilir, ancak benim için çok pratik bir yöntem olmaz. Bu şekilde bir çok alan var. Her kayıtta ve her okumada bu alanların get-set edilmesi zor olacak.
Sayıca fazla çoktan seçmeli alan (içerikleri çeşitli türleri farklı olabilir) olduğunu anlıyorum.
Yan yana bir sürü DBLookupComboBox kurmak bir yana sorgu durumuna göre farklı pencere tasarımları gerekeceğinden size hak veriyroum.
Alternatif olarak DBGrid üzerinden "PickList" ile ( cell/hücre bazında combobox diyebiliriz) yapılandırmak çözüm olabilir.
Bunun için bir örnek hazırladım incelemek isteyebilirsiniz.
Örnekte görmenizi istediğim konu; alan tipi ve alan ismini referans alarak seçenekleri bir kerede nasıl özelleştirebileceğiniz konusudur.
* MyGetText ve MySetText kısmında dönüşümü nasıl yaptığımızı kendi projenizde örneğe bakarak deneyebilirsiniz.
* Integer, Boolean veya String alan fark etmeksizin seçenek oluşturabilirsiniz.
MSSQL Server veritabanı ile örnekledim elimde kolayda bu vardı ama diğer tüm veritabanlarında aynen çalışır.
Proje dosyası bu mesaj ekindedir.
Kullanımı ve kaynak kodları indirmeden incelemek isteyenler için buraya paylaşıyorum.
Helper Class Unit
unit DBGridHelper;
interface
uses WinApi.Windows,
System.SysUtils, System.Classes, System.Types,
Vcl.DBGrids,
Data.DB;
Type
tDBGridHelper = class( TObject )
private
const
FEvetHayir : array[boolean] of string = ('Hayır','Evet');
FYesNo : array[boolean] of string = ('No','Yes');
FVarYok : array[0..1] of string = ('Yok','Var');
FAktifPasif : array[0..1] of string = ('Pasif', 'Aktif');
FYonler : array[0..4] of string = ('Yerinde', 'Yukarı', 'Aşağı', 'Sağa', 'Sola');
var
FDBGrid : TDBGrid;
FLog : TStrings;
procedure PreparePickList;
function ArrayIdx(const aText: string;
const aArray: array of string): integer;
function ListPick(const aArray: array of string): string;
function GetDBGrid: TDBGrid;
procedure SetDBGrid( value: TDBGrid );
procedure MyGetText(Sender: TField; var Text: String; DisplayText: Boolean);
procedure MySetText(Sender: TField; const Text: string);
procedure DBGrid_OnCellClick(Column: TColumn);
procedure LogLa( value: string );
public
constructor Create;
destructor Destroy; override;
property DBGrid : TDBGrid read GetDBGrid write SetDBGrid;
property Log : TStrings read FLog write FLog;
end;
implementation
{ tDBGridHelper }
constructor tDBGridHelper.Create;
begin
inherited;
end;
destructor tDBGridHelper.Destroy;
begin
inherited;
end;
function tDBGridHelper.ArrayIdx( const aText: string;
const aArray: array of string ): integer;
var
i : integer;
begin
result := -1;
i := Low(aArray);
while (i <= High(aArray)) and (result < 0) do
begin
if aText = aArray[i]
then result := i
else inc(i);
end;
end;
function tDBGridHelper.ListPick( const aArray: array of string ): string;
var
i : Integer;
begin
result := '';
for i := Low(aArray) to High(aArray)
do
result := result + aArray[i] + sLineBreak;
result := trim(result);
end;
procedure tDBGridHelper.PreparePickList;
var
i : Integer;
begin
if (FDBGrid.DataSource <> nil )
and (FDBGrid.DataSource.DataSet.Active)
then
begin
with FDBGrid.DataSource.DataSet do
begin
for i := 0 to FDBGrid.Columns.Count-1 do
begin
case FDBGrid.Columns[i].Field.DataType of
ftBoolean : // boolean
begin
if pos( 'EvetHayir', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FEvetHayir );
FDBGrid.Columns[i].DropDownRows := Length(FEvetHayir);
end;
if pos( 'YesNo', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FYesNo );
FDBGrid.Columns[i].DropDownRows := Length(FYesNo);
end;
end;
ftInteger : // integer
begin
if pos( 'VarYok', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FVarYok );
FDBGrid.Columns[i].DropDownRows := Length(FVarYok);
end;
if pos( 'YukariAsagi', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FYonler );
FDBGrid.Columns[i].DropDownRows := Length(FYonler);
end;
end;
ftString : // string
begin
if pos( 'AktifPasif', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FAktifPasif );
FDBGrid.Columns[i].DropDownRows := Length(FAktifPasif);
end;
end;
end;
end;
end;
end;
end;
function tDBGridHelper.GetDBGrid: TDBGrid;
begin
result := FDBGrid;
end;
procedure tDBGridHelper.SetDBGrid(value: TDBGrid);
var
i : Integer;
begin
FDBGrid := value;
PreparePickList();
FDBGrid.OnCellClick := DBGrid_OnCellClick;
for i := 0 to FDBGrid.Datasource.DataSet.FieldCount-1
do begin
FDBGrid.Datasource.DataSet.Fields[i].OnGetText := MyGetText;
FDBGrid.Datasource.DataSet.Fields[i].OnSetText := MySetText;
end;
for i := 0 to FDBGrid.Columns.Count-1
do
if FDBGrid.Columns[i].Width > 100
then
FDBGrid.Columns[i].Width := 100;
end;
procedure tDBGridHelper.MyGetText(Sender: TField; var Text: String;
DisplayText: Boolean);
begin
case TField(sender).DataType of
ftBoolean : // boolean
begin
if pos( 'EvetHayir', TField(sender).DisplayName ) > 0
then
Text := FEvetHayir[TField(sender).AsBoolean];
if pos( 'YesNo', TField(sender).DisplayName ) > 0
then
Text := FYesNo[TField(sender).AsBoolean];
end;
ftInteger : // integer
begin
if pos( 'VarYok', TField(sender).DisplayName ) > 0
then begin
Text := FVarYok[TField(sender).AsInteger];
end;
if pos( 'YukariAsagi', TField(sender).DisplayName ) > 0
then begin
Text := FYonler[TField(sender).AsInteger];
end;
end;
else
begin
Text := TField(sender).AsString; // def
end;
end;
end;
procedure tDBGridHelper.MySetText(Sender: TField; const Text: string);
begin
case TField(sender).DataType of
ftBoolean : // boolean
begin
if pos( 'EvetHayir', TField(sender).DisplayName ) > 0
then begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text + ' ( ' + IntToStr( ArrayIdx( Text, FEvetHayir ) ) + ' )');
TField(sender).AsBoolean := Boolean( ArrayIdx( Text, FEvetHayir ) );
end;
if pos( 'YesNo', TField(sender).DisplayName ) > 0
then begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text + ' ( ' + IntToStr( ArrayIdx( Text, FYesNo ) ) + ' )');
TField(sender).AsBoolean := Boolean( ArrayIdx( Text, FYesNo ) );
end;
end;
ftInteger : // integer
begin
if pos( 'VarYok', TField(sender).DisplayName ) > 0
then begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text + ' ( ' + IntToStr( ArrayIdx( Text, FVarYok ) ) + ' )');
TField(sender).AsInteger := ArrayIdx( Text, FVarYok );
end;
if pos( 'YukariAsagi', TField(sender).DisplayName ) > 0
then begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text + ' ( ' + IntToStr( ArrayIdx( Text, FYonler ) ) + ' )');
TField(sender).AsInteger := ArrayIdx( Text, FYonler )
end;
end;
else
begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text );
TField(Sender).AsString := Text; // def
end;
end;
end;
procedure tDBGridHelper.DBGrid_OnCellClick(Column: TColumn);
begin
if Column.PickList.Count > 0 then
begin
keybd_event(VK_F2, 0, 0,0);
keybd_event(VK_F2, 0, KEYEVENTF_KEYUP,0);
keybd_event(VK_MENU,0, 0,0);
keybd_event(VK_DOWN,0, 0,0);
keybd_event(VK_DOWN,0, KEYEVENTF_KEYUP,0);
keybd_event(VK_MENU,0, KEYEVENTF_KEYUP,0);
end;
end;
procedure tDBGridHelper.LogLa(value: string);
begin
if Assigned(FLog) then FLog.Add( value );
end;
end.
(21-02-2025, Saat: 13:31)mrmarman Adlı Kullanıcıdan Alıntı: Sayıca fazla çoktan seçmeli alan (içerikleri çeşitli türleri farklı olabilir) olduğunu anlıyorum.
Yan yana bir sürü DBLookupComboBox kurmak bir yana sorgu durumuna göre farklı pencere tasarımları gerekeceğinden size hak veriyroum.
Alternatif olarak DBGrid üzerinden "PickList" ile ( cell/hücre bazında combobox diyebiliriz) yapılandırmak çözüm olabilir.
Bunun için bir örnek hazırladım incelemek isteyebilirsiniz.
Örnekte görmenizi istediğim konu; alan tipi ve alan ismini referans alarak seçenekleri bir kerede nasıl özelleştirebileceğiniz konusudur.
* MyGetText ve MySetText kısmında dönüşümü nasıl yaptığımızı kendi projenizde örneğe bakarak deneyebilirsiniz.
* Integer, Boolean veya String alan fark etmeksizin seçenek oluşturabilirsiniz.
MSSQL Server veritabanı ile örnekledim elimde kolayda bu vardı ama diğer tüm veritabanlarında aynen çalışır.
Proje dosyası bu mesaj ekindedir.
Kullanımı ve kaynak kodları indirmeden incelemek isteyenler için buraya paylaşıyorum.
Helper Class Unit
unit DBGridHelper;
interface
uses WinApi.Windows,
System.SysUtils, System.Classes, System.Types,
Vcl.DBGrids,
Data.DB;
Type
tDBGridHelper = class( TObject )
private
const
FEvetHayir : array[boolean] of string = ('Hayır','Evet');
FYesNo : array[boolean] of string = ('No','Yes');
FVarYok : array[0..1] of string = ('Yok','Var');
FAktifPasif : array[0..1] of string = ('Pasif', 'Aktif');
FYonler : array[0..4] of string = ('Yerinde', 'Yukarı', 'Aşağı', 'Sağa', 'Sola');
var
FDBGrid : TDBGrid;
FLog : TStrings;
procedure PreparePickList;
function ArrayIdx(const aText: string;
const aArray: array of string): integer;
function ListPick(const aArray: array of string): string;
function GetDBGrid: TDBGrid;
procedure SetDBGrid( value: TDBGrid );
procedure MyGetText(Sender: TField; var Text: String; DisplayText: Boolean);
procedure MySetText(Sender: TField; const Text: string);
procedure DBGrid_OnCellClick(Column: TColumn);
procedure LogLa( value: string );
public
constructor Create;
destructor Destroy; override;
property DBGrid : TDBGrid read GetDBGrid write SetDBGrid;
property Log : TStrings read FLog write FLog;
end;
implementation
{ tDBGridHelper }
constructor tDBGridHelper.Create;
begin
inherited;
end;
destructor tDBGridHelper.Destroy;
begin
inherited;
end;
function tDBGridHelper.ArrayIdx( const aText: string;
const aArray: array of string ): integer;
var
i : integer;
begin
result := -1;
i := Low(aArray);
while (i <= High(aArray)) and (result < 0) do
begin
if aText = aArray[i]
then result := i
else inc(i);
end;
end;
function tDBGridHelper.ListPick( const aArray: array of string ): string;
var
i : Integer;
begin
result := '';
for i := Low(aArray) to High(aArray)
do
result := result + aArray[i] + sLineBreak;
result := trim(result);
end;
procedure tDBGridHelper.PreparePickList;
var
i : Integer;
begin
if (FDBGrid.DataSource <> nil )
and (FDBGrid.DataSource.DataSet.Active)
then
begin
with FDBGrid.DataSource.DataSet do
begin
for i := 0 to FDBGrid.Columns.Count-1 do
begin
case FDBGrid.Columns[i].Field.DataType of
ftBoolean : // boolean
begin
if pos( 'EvetHayir', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FEvetHayir );
FDBGrid.Columns[i].DropDownRows := Length(FEvetHayir);
end;
if pos( 'YesNo', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FYesNo );
FDBGrid.Columns[i].DropDownRows := Length(FYesNo);
end;
end;
ftInteger : // integer
begin
if pos( 'VarYok', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FVarYok );
FDBGrid.Columns[i].DropDownRows := Length(FVarYok);
end;
if pos( 'YukariAsagi', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FYonler );
FDBGrid.Columns[i].DropDownRows := Length(FYonler);
end;
end;
ftString : // string
begin
if pos( 'AktifPasif', FDBGrid.Columns[i].Field.DisplayName ) > 0
then begin
FDBGrid.Columns[i].PickList.Text := ListPick( FAktifPasif );
FDBGrid.Columns[i].DropDownRows := Length(FAktifPasif);
end;
end;
end;
end;
end;
end;
end;
function tDBGridHelper.GetDBGrid: TDBGrid;
begin
result := FDBGrid;
end;
procedure tDBGridHelper.SetDBGrid(value: TDBGrid);
var
i : Integer;
begin
FDBGrid := value;
PreparePickList();
FDBGrid.OnCellClick := DBGrid_OnCellClick;
for i := 0 to FDBGrid.Datasource.DataSet.FieldCount-1
do begin
FDBGrid.Datasource.DataSet.Fields[i].OnGetText := MyGetText;
FDBGrid.Datasource.DataSet.Fields[i].OnSetText := MySetText;
end;
for i := 0 to FDBGrid.Columns.Count-1
do
if FDBGrid.Columns[i].Width > 100
then
FDBGrid.Columns[i].Width := 100;
end;
procedure tDBGridHelper.MyGetText(Sender: TField; var Text: String;
DisplayText: Boolean);
begin
case TField(sender).DataType of
ftBoolean : // boolean
begin
if pos( 'EvetHayir', TField(sender).DisplayName ) > 0
then
Text := FEvetHayir[TField(sender).AsBoolean];
if pos( 'YesNo', TField(sender).DisplayName ) > 0
then
Text := FYesNo[TField(sender).AsBoolean];
end;
ftInteger : // integer
begin
if pos( 'VarYok', TField(sender).DisplayName ) > 0
then begin
Text := FVarYok[TField(sender).AsInteger];
end;
if pos( 'YukariAsagi', TField(sender).DisplayName ) > 0
then begin
Text := FYonler[TField(sender).AsInteger];
end;
end;
else
begin
Text := TField(sender).AsString; // def
end;
end;
end;
procedure tDBGridHelper.MySetText(Sender: TField; const Text: string);
begin
case TField(sender).DataType of
ftBoolean : // boolean
begin
if pos( 'EvetHayir', TField(sender).DisplayName ) > 0
then begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text + ' ( ' + IntToStr( ArrayIdx( Text, FEvetHayir ) ) + ' )');
TField(sender).AsBoolean := Boolean( ArrayIdx( Text, FEvetHayir ) );
end;
if pos( 'YesNo', TField(sender).DisplayName ) > 0
then begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text + ' ( ' + IntToStr( ArrayIdx( Text, FYesNo ) ) + ' )');
TField(sender).AsBoolean := Boolean( ArrayIdx( Text, FYesNo ) );
end;
end;
ftInteger : // integer
begin
if pos( 'VarYok', TField(sender).DisplayName ) > 0
then begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text + ' ( ' + IntToStr( ArrayIdx( Text, FVarYok ) ) + ' )');
TField(sender).AsInteger := ArrayIdx( Text, FVarYok );
end;
if pos( 'YukariAsagi', TField(sender).DisplayName ) > 0
then begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text + ' ( ' + IntToStr( ArrayIdx( Text, FYonler ) ) + ' )');
TField(sender).AsInteger := ArrayIdx( Text, FYonler )
end;
end;
else
begin
LogLa('GET: ' + TField(sender).DisplayName + ' = ' + Text );
TField(Sender).AsString := Text; // def
end;
end;
end;
procedure tDBGridHelper.DBGrid_OnCellClick(Column: TColumn);
begin
if Column.PickList.Count > 0 then
begin
keybd_event(VK_F2, 0, 0,0);
keybd_event(VK_F2, 0, KEYEVENTF_KEYUP,0);
keybd_event(VK_MENU,0, 0,0);
keybd_event(VK_DOWN,0, 0,0);
keybd_event(VK_DOWN,0, KEYEVENTF_KEYUP,0);
keybd_event(VK_MENU,0, KEYEVENTF_KEYUP,0);
end;
end;
procedure tDBGridHelper.LogLa(value: string);
begin
if Assigned(FLog) then FLog.Add( value );
end;
end.