Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
LiveBindings belası!
#1
Merhaba Arkadaşlar,

Bu foruma yeni üye olduğumdan öncelikle kendimi tanıtayım.
Ben 50 yaşında bir developer eskisiyim. (gerçi Turbo Pascal/Borland/Embarcadero/Idera/Delphi dünyasının yaş ortalaması benden çok uzakta değil :Smile  ).
Delphi 3.0 ile 90'lı yıllarda çok çalıştım. .Net kütüphanelerinin Delphi'den araklanmasına tanık oldum. O zamanlar VCL/RTL'i dibine kadar bilirdik (obje sayısı az değildi ama şimdilerde uçmuş).

25 sene sonra bir mobil uygulama için tekrar Delphi kullanıyorum (RAD Studo 10.1 Berlin Update 2). Aradan geçen 25 senede -özel amaçlı olanlar hariç- piyasaya sürülen dillerden ve "kıçtan uydurma" framework'lerden hiçbirinin Delphi kadar sağlam temellere dayanmadığını gördüğümden eski dostumla tekrar kucaklaştık.

Şu andaki en büyük sorunum FireDAC / FMX için data-aware kontroller olmaması (TDBGrid gibi). Bütün bu framework çok akıllıca ama data binding için ille de LiveBindings mi kullanmak gerekiyor?

LiveBindings ile ilgili sıkıntı şu: Her ne kadar iş bakış açısından daha rahat anlaşılabilir (mesela İş Analisti) ve kod gerektirmiyor gibi gözükse bu tür yaklaşımlar bir yerlerde tıkanmaya mahkumdur. Görsel bağlantılar bir kod üretmediği sürece detaya müdahale etmek mümkün değil. 

Örneğin, eskiden, herhangi bir data-aware kontrolde Datasource'u runtime'da herhangi bir TDatasource'a bağlayabilirdik. Diyelim ki bu bir TDBGrid olsun; grid seviyesinde alan (field) tanımlarını özellikle (explicitly) yapmadığınız sürece grid bağlı olduğu TDataset'in alanlarını dinamik olarak alıp gösterebiliyordu. Böylece uygulamada akılcı bir tasarım ile kontrol sayısını azaltıp her birini çok amaçlı kullanmak (mesela kullanıcı hangi tab'da çalışıyorsa onunla ilgili veri setini aynı grid'de göstermek gibi) bellek kullanımı/footprint vs. azaltılabiliyordu.

Benzer bir denemeyi TFDTable - TGrid LiveBindings bağlantısı ile yaptığımda (mesela TFDTable'ın tablosunu değiştirip tekrar açtığımda) livebindings metadası yüzünden "o field bulunamadı vs.) hataları alıyorum. Galiba bütün metadatayı TBindingList gibi bir şeyin içinde tutuyor.

Kontrolleri livebindings yaklaşımı dışında bir veri setine bağlamak için başka bir yöntem var mı? Yoksa "eski güzel günleri anarak" yas tutup yola bununla devam mı edeyim?

Açıkçası, sırf birkaç tane event kodlamamak ve daha görsel bir tasarım olsun diye bu şekilde yapıldıysa çok yazık olmuş. LiveBindings gibi görsel bir araç kullanılıp bunun için de kod üretilip kodun kendisine müdahale etme şansı tanınmalıydı. Bunun için kontrol bazında Datasource property'sinden vazgeçmeye gerek yoktu.

sevgiyle kalın, evde kalın,
Behçet Tolga
Cevapla
#2
Behcet bey Live binding daha önce kullanmadım. Size net cevap veremem ama bi kaç şey karalamak isterim.
Öncelikle Android uygulmanızı Play Store da yayınlayacaksanız bir an önce 10.3.3 sürümüne geçmelisiniz, aksi halde 32 ve 64 bit uygulamayı beraber barındıran .aab dosyasını elinizdeki sürüm oluşturamaz.

Siz eğer uzak veritabanına bağlanacaksanız android yada ios üzerinden Data snap daha iyi bir tercih olabilir yada db kullanım sıklığına bağlı olarak ilk 4 eğitim videosunda anlatılan postgres web servis ile de yapabilirsiniz. SQlite gibi local kullanacaksanız Sqlconnection , Firebird yada Unidac kullanabilirsiniz. Bence ilk tercihiniz Unidac olsun Ben 10.2 de hazırladığım VCL ygulama Firedac yüzünden 10.3 de bir çok hata verdi.

Bağlantı ve rveri çekme işlemlerinin runtime da yapacaksanız kullandığınız componentin sql kodunu yazmalısınız.

Daha spesifik sorunuz lursa elimden geldiğince yardımcı olalım ki Delphiden vazgeçmeyin.
Genelde telefondan ingilizce klavye ile ileti gönderiyorum.
Cevapla
#3
Selamlar 4-5 sene önce böyle bir helper karalamıştım FMX için belki işinize yarar. Livebinding değil ama az biraz kolaylastırıyordu.

https://github.com/barisatalay/GridHelper
Yeni Nesil Yazılımcı
Linkedin: https://tr.linkedin.com/in/barisatalay07
WWW
Cevapla
#4
Cevaplar için teşekkürler,

>>Öncelikle Android uygulmanızı Play Store da yayınlayacaksanız bir an önce 10.3.3 sürümüne geçmelisiniz, aksi halde 32 ve 64 bit uygulamayı beraber barındıran .aab dosyasını elinizdeki sürüm oluşturamaz.

Bunu öğrenmek iyi oldu; tedbirimi alırım.

>>Ben 10.2 de hazırladığım VCL ygulama Firedac yüzünden 10.3 de bir çok hata verdi.

Şu aşamada 3rd party ürün kullanmak istemiyorum; FireDAC yeterli gözüküyor. Upgrade edince ne tip sorunlarla karşılaştınız ki? Normalde Delphi'nin geriye dönük uyumluluğu çok iyiydi.

LiveBindings meselesi aslında altta kullanılan veri çekme (data fetch) teknoloji ve yönteminden bağımsız bir konu. Veri bir şekilde dataset'e geldiğinde ekrandaki bileşene (presentation layer) nasıl aktarılacağı ile ilgili. Yani Datasnap, FireDAC, xDAC farketmiyor.

Dün gece epey bir mesai yaptım ve LiveBindings işini çözdüm ve durumu kabullendim (gibi). Yalnız gördüğüm kadarıyla biraz daha yavaş çalışıyor sanki.

Siz LiveBinding hiç kullanmadıysanız ekrandaki bileşenlerde veriyi nasıl gösteriyorsunuz? Başka bir yöntem mi var?

sağlıcakla kalın,
Cevapla
#5
(24-03-2020, Saat: 17:31)behcet.tolga Adlı Kullanıcıdan Alıntı: Cevaplar için teşekkürler,

>>Öncelikle Android uygulmanızı Play Store da yayınlayacaksanız bir an önce 10.3.3 sürümüne geçmelisiniz, aksi halde 32 ve 64 bit uygulamayı beraber barındıran .aab dosyasını elinizdeki sürüm oluşturamaz.

Bunu öğrenmek iyi oldu; tedbirimi alırım.

>>Ben 10.2 de hazırladığım VCL ygulama Firedac yüzünden 10.3 de bir çok hata verdi.

Şu aşamada 3rd party ürün kullanmak istemiyorum; FireDAC yeterli gözüküyor. Upgrade edince ne tip sorunlarla karşılaştınız ki? Normalde Delphi'nin geriye dönük uyumluluğu çok iyiydi.

LiveBindings meselesi aslında altta kullanılan veri çekme (data fetch) teknoloji ve yönteminden bağımsız bir konu. Veri bir şekilde dataset'e geldiğinde ekrandaki bileşene (presentation layer) nasıl aktarılacağı ile ilgili. Yani Datasnap, FireDAC, xDAC farketmiyor.

Dün gece epey bir mesai yaptım ve LiveBindings işini çözdüm ve durumu kabullendim (gibi). Yalnız gördüğüm kadarıyla biraz daha yavaş çalışıyor sanki.

Siz LiveBinding hiç kullanmadıysanız ekrandaki bileşenlerde veriyi nasıl gösteriyorsunuz? Başka bir yöntem mi var?

sağlıcakla kalın,

Firedac TFDQuery nesnesi ile Para data tipi için Decimal(15,2) kullanmıştım firebird veritabanında.
Uygulamayı 10.3.3 de tekrar derlediğimde bu alanları TBcd hatası vererek yeniden her bir query için field leri silip eklemem gerekti.

procedure içi hesaplamalarda .Value yerine .AsCurrency olaraak değiştirmek zorunda kaldım. Boş yere vaktimi aldı.

1XomMm.png
Standart bir datasnap bağlantısını bu şekilde yapmıştım aldığım veri yığınını string grid içinde göstermiştim.
Client Data Set ile her satırı string grid içine yazdırdım. Live binding kullanmadan.Run time da basit bir Clien Data set ile Data snapdan veri alma():
 with Datamodule1.ClientArac do
   begin
     active:=false;
     Komut:='SELECT ADSOYAD ......... '+
             'FROM CARI_HESAP C '+
             'INNER JOIN MUSTERI M ON C.CARI_KOD=M.MUSTERINU '+
             'WHERE (KAPALI=FALSE) AND (BORC IS NOT NULL) '+
             'ORDER BY C.TARIH DESC';


     CommandText:=Komut;
     

     Active:=true;
     first;
     i:=0;

     while not eof do
     begin

       GRidlist.RowCount:=gridlist.RowCount + 1;
       
       gridlist.Cells[0,i].ToBoolean(BoolToStr (FieldByName('KAPALI').AsBoolean)) ;
       gridlist.Cells[1,i]:=FieldByName('ADSOYAD').AsString;
       gridlist.Cells[2,i]:=currtostr(FieldByName('BORC').AsCurrency);
       gridlist.Cells[4,i]:=CURRtostr(FieldByName('ODEME').AsCurrency);
       gridlist.Cells[5,i]:=currtostr(FieldByName('BAKIYE').AsCurrency);
       gridlist.Cells[6,i]:=FieldByName('KALEM').AsString;
       if not(FieldByName('TARIH').AsDateTime=Null) then gridlist.Cells[7,i]:=datetostr(FieldByName('TARIH').AsDateTime);
       gridlist.Cells[8,i]:=FieldByName('ACIKLAMA').AsString;
       gridlist.Cells[9,i]:=inttostr(FieldByName('CARI_KOD').AsInteger);
       gridlist.Cells[10,i]:=inttostr(FieldByName('ID').Asinteger);


       i:=i +1;
      next;
     end;

   end;
Siz strging grid yerine OrangeUI ile dbgrid olarak da verileir çekebilirsiniz. Kullanışlı bir komponent seti.
Genelde telefondan ingilizce klavye ile ileti gönderiyorum.
Cevapla
#6
Photo 
Anladım. Bu yöntemle tabii yapılabilir ama Excel'de macro yazmak gibi bir hale dönüşüyor iş. Ayrıca cell'e bu şekilde doğrudan yazınca arada başka event'ler de fire ediyor olabilir; yüksek veri miktarında performans sıkıntısı yaşanır diye düşünüyorum.

Orange bileşenleri güzel görünüyor ve 99$ pahalı da değil. Gene de projemi şu anda Çinli kardeşlerin merhametine emanet etmek istemiyorum.  Smile

LiveBindings örnek görüntüsü ekte. Sanırım artık tek geçerli yöntem bu.
Siz de kullanmadıysanız bir an önce inceleyip kullanmaya başlamanızı öneriyorum.

   

sevgiler,
Cevapla
#7
(25-03-2020, Saat: 00:11)behcet.tolga Adlı Kullanıcıdan Alıntı: Anladım. Bu yöntemle tabii yapılabilir ama Excel'de macro yazmak gibi bir hale dönüşüyor iş. Ayrıca cell'e bu şekilde doğrudan yazınca arada başka event'ler de fire ediyor olabilir; yüksek veri miktarında performans sıkıntısı yaşanır diye düşünüyorum.

Orange bileşenleri güzel görünüyor ve 99$ pahalı da değil. Gene de projemi şu anda Çinli kardeşlerin merhametine emanet etmek istemiyorum.  Smile

LiveBindings örnek görüntüsü ekte. Sanırım artık tek geçerli yöntem bu.
Siz de kullanmadıysanız bir an önce inceleyip kullanmaya başlamanızı öneriyorum.



sevgiler,

Woll2Woll'un FirePower bileşenlerini kullanabilirsiniz. Kendi DBGridlerini ve diğer bileşenlerini aynen VCL'deki gibi TDatasource ve TDataset bağlantılarıyla sağlıyorlar. Oldukça kullanışlı. İyi de çalışıyor. Tavsiye ederim. 

OrangeUI gayet iyi, yalnız küçük (?) bir kaç problemle karşılaştım onda. Eğer OrangeUI kullanırken TFrame'leri başka bir TFrame'den türetiyorsanız hata veriyor. Türetmeyince de eski tarz programlamadan kurtulamıyorsunuz.
Ayrıca bileşenlerinde LiveBindings'i kullanamıyorsunuz kesinlikle. Delphi'yi kırıyor!
Umarım sonraki sürümde düzeltirler bu hataları.
Cevapla
#8
Merhaba,

@behcet.tolga Delphi dünyasına tekrar hoşgeldiniz Smile

Önce işin biraz daha tasarım kısmından bahsedelim. Maalesef Delphi'nin veri tabanı bileşenleri o kadar pratik ki, biz Delphi programcıları arayüz ile iş katmanını birbirinden ayırmayı öğrenemedik. Bugün Delphi'nin bu kadar az kullanılmasındaki en sebeplerden birisi de maalesef budur, çünkü uzun soluklu projelerde bu ayırımın olmaması çok ciddi sorunlar yaratıyor. Örneğin arayüz yenilemesi mümkün olmuyor. Yeni alanlar eklendiğinde işler içinden çıkılmaz hale geliyor. Veriyi doğrulama (validate) işlemleri ilgili ilgisiz yerlerde yapılıyor. Bir ekip tarafından geliştirilen projelerde iş paylaşımı çok zor yapılıyor. Daha bir sürü ek sorun çıkıyor. Sonuç olarak projenin ana programcısı işten ayrıldığında maalesef proje de bir süre sonra tıkanıyor veya çok ciddi derecede sekteye uğruyor. Bütün bunlar Delphi'nin yanlışı mı? Değil, ama biz programcılar Delphi'nin sunduğu bu avantajları maalesef çok yanlış kullandık.

Şimdi de LiveBindings geldi. LiveBindings aslında yeni bir şey değil. Emin değilim ama sanırım Microsoft'tan alındı. İlk başta çok pratik gibi görünüyor. Tıpkı Delphi'nin veri tabanı bileşenleri gibi Smile Ama maalesef bunlar da veri tabanı bileşenleri ile aynı sonucu çıkıyor. Aradaki tek fark şu: Eskiden sadece TDBxyz bileşenlerini TDataSource aracılığı ile bağlardık, şimdi herşeyi birbiri ile bağlayabiliyoruz Big Grin Cümle ilk başta pırıl pırıl parlıyor, ama veri tabanı bileşenlerinde yaşadığımız sorunların çok daha fazlası masaya geldi. Evet, küçük projeler için çok güzel, ama proje biraz büyüdüğü zaman hiç iyi bir fikir değil.

Peki ne yapmak gerekiyor? Çok basit. Diğer programlama dillerini ve onların kütüphanelerini geliştiren programcılar, Delphi'nin geliştiricilerinden daha salak insanlar değiller. O yüzden herşeyin çok daha anlaşılır ve yönetilebilir olduğu sistemler geliştiriyorlar. Bu sistemler de tahmine edebileceğiniz gibi OOP üzerine kurulu. Yani asıl amaç bütün veriyi nesne olarak yönetmek. Nesneler üzerinde işlem yapmak ve arayüzü sadece "arayüz" olarak kullanmak. İş kuralları arayüzlerde değil, nesnelerde olsun demek. Bunun birçok avantajı var. Öncelikle iş kurallarını ve arayüzü iki farklı programcı kodlayabilir (tabii ortak çalışacaklar Smile ). İş kuralları değiştiğinde bunun nerede tanımlandığını bildiğiniz için aramak zorunda değilsiniz. Arayüze çok fazla iş yüklemediğiniz için süsleyebilirsiniz (özellikle FMX'de, çünkü FMX'de arayüz animasyonları yapmak çok kolay). Projenizi birden fazla platforma taşımak çok daha kolay olur. Çok katmanlı mimariye geçmek veya multithread kod yazmak çok daha kolay olur. Daha sayısız avantajı var. Bunların yanında ciddi bir iki de dezavantajı var :Smile Benim açımdan iki temel dezavantajı var: 1. Veri erişimi eskisine göre daha yavaş olur. Örneğin VCL uygulamalarında ekranda binlerce kayıt gösterebilirsiniz (niye bilmiyorum, ama evet, gösterebilirsiniz). Ama objelerle çalışıyorsanız bir seferde binlerce objenin yaratılması gibi işlemler vakit alacağı için Object Pool benzeri optimizasyonlar yapmanız gerekebilir (bence binlerce kayıt göstermeyin). 2. Projenin başında daha fazla kod yazmanı gerekiyor. Eskiden veri tabanında tabloları yaratıp Delphi'den anında görebiliyordunuz. Artık bu yöntem geçerli değil. ORM toolları bu konuda yardımcı olabilir. Bazı ORM kütüphanelerinde TDataSource bağlantısı da var (TDataSource bağlantısı bana "cehenneme giden yol iyi niyet taşlarıyla döşelidir" Alman atasözünü hatırlatıyor Smile ).

Gelelim sizin durumunuza Smile Bence, henüz başındayken bu işi kuralına göre yapın. Yani verilerinizi tuttuğunuz yerde bir sunucu uygulamanız olsun. Bunu da DataSnap'le falan yapmayın, hiç gerek yok. Indy'nin TIdHttpServer bileşeni ile kendiniz kodlayın. Yapacağınız aslında çok basit. Size gelen isteklerin cevaplarını göndereceksiniz. Tabii güvenlik için de bir iki şey yazacaksınız. Nesnelerinizi nasıl serialize/deserialize edeceğiniz size kalmış. Örneğin JSon kullanacaksanız (küçük miktarda veri transferleri için tavsiye ederim) JSonDataObjects'i tavsiye ederim. Hem hızlı, hem kolay. Büyük verileri için de binary bir sistem geliştirin. Bunlar için de standartlar var. İsterseniz kendize göre bir şey geliştirin. Sonuçta bu kısım ileride anında değiştirilebilir olacak (çünkü sadece nesneleri serialize/deserialize ediyorsunuz). İstemci tarafı artık sadece nesneleri aldığı için işler daha kolay. Verileri arayüze aktarın veya arayüzden verileri alıp nesneleri güncelleyin. Güncellenmiş nesneleri sunucuya gönderin vs.

Örnek kodun FMX dosyası: 
object Form1: TForm1
 Left = 0
 Top = 0
 Caption = 'Form1'
 ClientHeight = 473
 ClientWidth = 557
 FormFactor.Width = 320
 FormFactor.Height = 480
 FormFactor.Devices = [Desktop]
 DesignerMasterStyle = 0
 object grdTest: TGrid
   CanFocus = True
   ClipChildren = True
   Position.X = 20.000000000000000000
   Position.Y = 64.000000000000000000
   Size.Width = 517.000000000000000000
   Size.Height = 381.000000000000000000
   Size.PlatformDefault = False
   TabOrder = 0
   RowCount = 0
   OnGetValue = grdTestGetValue
   OnSetValue = grdTestSetValue
   Viewport.Width = 513.000000000000000000
   Viewport.Height = 356.000000000000000000
   object icId: TIntegerColumn
     Tag = 1
     Header = 'Id'
   end
   object scValue: TStringColumn
     Tag = 2
     Header = 'Value'
     Size.Width = 252.000000000000000000
   end
   object ccPrice: TCurrencyColumn
     Tag = 3
     Header = 'Price'
   end
 end
 object Button1: TButton
   Position.X = 48.000000000000000000
   Position.Y = 24.000000000000000000
   TabOrder = 2
   Text = 'Fill'
   OnClick = Button1Click
 end
 object Button2: TButton
   Position.X = 140.000000000000000000
   Position.Y = 24.000000000000000000
   TabOrder = 1
   Text = 'Show'
   OnClick = Button2Click
 end
end

Pas dosyası:
unit Unit1;

interface

uses
 System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
 FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Rtti,
 FMX.Grid.Style, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Grid,

 System.Generics.Collections, FMX.StdCtrls;

const
 COLUMN_TAG_ID = 1;
 COLUMN_TAG_VALUE = 2;
 COLUMN_TAG_PRICE = 3;

type
 TMyObject = class
 private
   FId: Integer;
   FValue: string;
   FPrice: Currency;
   procedure SetId(const Value: Integer);
   procedure SetPrice(const Value: Currency);
   procedure SetValue(const Value: string);
 public
   property Id: Integer read FId write SetId;
   property Value: string read FValue write SetValue;
   property Price: Currency read FPrice write SetPrice;
 end;

 TMyObjectList = class(TObjectList<TMyObject>)
 end;

 TForm1 = class(TForm)
   grdTest: TGrid;
   icId: TIntegerColumn;
   scValue: TStringColumn;
   Button1: TButton;
   Button2: TButton;
   ccPrice: TCurrencyColumn;
   procedure grdTestGetValue(Sender: TObject; const ACol, ARow: Integer;
     var Value: TValue);
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure grdTestSetValue(Sender: TObject; const ACol, ARow: Integer;
     const Value: TValue);
 private
   FObjectList: TMyObjectList;
   procedure FillObjectList;
   procedure ShowObjectList;
 public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
 end;

var
 Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
 FillObjectList;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 ShowObjectList;
end;

constructor TForm1.Create(AOwner: TComponent);
begin
 inherited;
 FObjectList := TMyObjectList.Create;
end;

destructor TForm1.Destroy;
begin
 FObjectList.Free;
 inherited;
end;

procedure TForm1.FillObjectList;
var
 I: Integer;
 MyObject: TMyObject;
begin
 for I := 1 to 1000 do
 begin
   MyObject := TMyObject.Create;
   MyObject.Id := I;
   // MyObject.Value := 'Value ' + IntToStr(I);
   // MyObject.Price := 0;

   FObjectList.Add(MyObject);
 end;
end;

procedure TForm1.grdTestGetValue(Sender: TObject; const ACol, ARow: Integer;
 var Value: TValue);
var
 MyObject: TMyObject;
 Column: TColumn;
begin
 MyObject := FObjectList.Items[ARow];
 Column := (Sender as TGrid).ColumnByIndex(ACol);

 case Column.Tag of
   COLUMN_TAG_ID: Value := MyObject.Id;
   COLUMN_TAG_VALUE: Value := MyObject.Value;
   COLUMN_TAG_PRICE: Value := MyObject.Price;
   else
     raise Exception.Create('Unknown column!');
 end;
end;

procedure TForm1.grdTestSetValue(Sender: TObject; const ACol, ARow: Integer;
 const Value: TValue);
var
 MyObject: TMyObject;
 Column: TColumn;
begin
 MyObject := FObjectList.Items[ARow];
 Column := (Sender as TGrid).ColumnByIndex(ACol);

 case Column.Tag of
   COLUMN_TAG_ID: MyObject.Id := StrToInt(Value.AsString);
   COLUMN_TAG_VALUE: MyObject.Value := Value.AsString;
   COLUMN_TAG_PRICE: MyObject.Price := Value.AsCurrency;
   else
     raise Exception.Create('Unknown column!');
 end;
end;

procedure TForm1.ShowObjectList;
begin
 grdTest.BeginUpdate;
 try
   grdTest.RowCount := FObjectList.Count;
 finally
   grdTest.EndUpdate;
 end;
end;

{ TMyObject }

procedure TMyObject.SetId(const Value: Integer);
begin
 // Business Logic için Örnek olsun
 FId := Value;

 if FValue = '' then
   FValue := 'Value ' + IntToStr(FId);

 FPrice := FId * 10;
end;

procedure TMyObject.SetPrice(const Value: Currency);
begin
 FPrice := Value;
end;

procedure TMyObject.SetValue(const Value: string);
begin
 FValue := Value;
end;

end.

Ben bu örnekte bir TGrid koydum. 3 tane sütun ekledim. Sütunların yerleri değişince sorun olmasın diye de her sütunun Tag özelliğine değer verdim. Hangi sütun ne işe yaradığını buradan ayırdediyorum. İş mantığını nesnenin içine ekledim, ama normalde böyle yapmazdım. Normalde veri katmanı ile iş katmanını da ayırmak lazım, ama bu kadarı bile iş görür Smile

Yazdıklarımdan pratik sonuçlar çıkar mı bilmiyorum. Umarım işinize yarar.

İyi çalışmalar
Cevapla
#9
(23-03-2020, Saat: 17:19)behcet.tolga Adlı Kullanıcıdan Alıntı: LiveBindings belası!

sevgiyle kalın, evde kalın,
Behçet Tolga


Kesinlikle size katılıyorum. Firemonkey ile VCL konusundaki bütün alışkanlıklarımız ve tecrübelerimiz yerle bir oldu. Bizim bin bir zorlukla yaptığımız şeyleri Java'cıların veya HTML-JS cilerin iki dakikada, daha stabil ve daha görsel şekilde yaptığını görünce onları kıskanıyorum.
WWW
Cevapla
#10
@Bahadir.Alkac, "Birisine nasıl yardımcı olunur"u göstermiş yukarıda. Emeğine sağlık...
There's no place like 127.0.0.1
WWW
Cevapla




Konuyu Okuyanlar: 1 Ziyaretçi