Merhaba,
Firemonkey tarafında (kendi içinde ve faklı listViewler arasında) listView drag and dpor yapabileceğim, forumda ve nette elle tutulur bir kod bulamadım.
Elinde kod olan arkadaşlar paylaşımda bulunursa sevinirim.
FMX derken Windows altında yapıyorsunuz değil mi ?
Bu size hazırladığım örnek sadece
kaynak item ve
index numarası ile
taşıdığınız hedef item ve
index numarasını verecektir. Kaynak ve hedefi biliyorum, araya nasıl yerleştireceğim, çoklu / multidrag nasıl yaparım vb. gibi bir soru gelecek gibi ama hadi kayırlısı
İşlem çok teknik olduğundan direkt örnek kod ile cevap verdim, bundan sonrası küçük / basit bir insert Item ve swap Item işlemidir.
Boş bir MultiDevice (Win) proje açın, içinde ListView1 ve ListView2 adında iki TListView koyun.
Bir de TImage koyun Image1 olsun içinde de listview Item'ini taşırken görmek istediğiniz icon tipinde bir resim koyun. Bu da size bonus özellik.
Dilerseniz ileride de bunu bir CLASS yapıp iki ListView'i bu class'a nesne olarak insert eder otomatik özellik kazandırabilirsiniz. Ben bu şekilde CLASS halinde kullanıyorum ama sizin için şu aşamada bu kısım yeterli.
procedure TForm1.FormCreate(Sender: TObject);
Var
i : Integer;
begin
With ListView1.ItemAppearanceObjects.ItemObjects.Accessory do begin
AccessoryType := TAccessoryType.Checkmark;
Visible := False;
end;
With ListView2.ItemAppearanceObjects.ItemObjects.Accessory do begin
AccessoryType := TAccessoryType.Checkmark;
Visible := False;
end;
ListView1.OnDragDrop := ListView1DragDrop;
ListView1.OnDragOver := ListView1DragOver;
ListView1.OnMouseMove := ListView1MouseMove;
ListView1.OnDblClick := ListView1DblClick;
ListView2.OnDragDrop := ListView1DragDrop;
ListView2.OnDragOver := ListView1DragOver;
ListView2.OnMouseMove := ListView1MouseMove;
ListView2.OnDblClick := ListView1DblClick;
for i := 0 to 20 do begin
With ListView1.Items.Add do
begin
Text := Format('ListView1Item_%.2d', [i]);
// diğer atamalar vs.
end;
With ListView2.Items.Add do
begin
Text := Format('ListView2Item_%.2d', [i]);
// diğer atamalar vs.
end;
end;
end;
function GetIndexAtPos(LV: TListView; TP: TPointF): Integer;
var
I : Integer;
TR: TRectF;
begin
Result := -1;
for I := 0 to LV.Items.Count-1 do begin
TR := LV.GetItemRect(I);
if TR.Contains(TP) then begin
Result := I;
Break;
end;
end;
end;
procedure TForm1.ListView1DblClick(Sender: TObject);
begin
if TListView(Sender).Selected = nil then Exit;
With TListViewItem( TListView(Sender).Selected ).Objects.AccessoryObject
do Visible := NOT Visible;
end;
procedure TForm1.ListView1DragDrop(Sender: TObject; const Data: TDragObject;
const Point: TPointF);
var
obj : IControl;
Index: Integer;
begin
obj := ObjectAtPoint(Screen.MousePos);
if obj <> nil then begin
Index := GetIndexATPos ( TListView(Sender), Point);
if Index <> -1 then begin
TListView(Sender).ItemIndex := Index;
ShowMessage ('Kaynak: ' + TListViewItem(Data.Source).Text + ' Idx: ' + TListViewItem(Data.Source).Index.ToString + ' Hedef : ' + TListViewItem(TListView(Sender).Selected).text + ' Idx: ' + TListView(obj).ItemIndex.ToString );
end;
end;
end;
procedure TForm1.ListView1DragOver(Sender: TObject; const Data: TDragObject;
const Point: TPointF; var Operation: TDragOperation);
begin
Operation := TDragOperation.Move;
end;
procedure TForm1.ListView1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Single);
begin
if (ssLeft in Shift) and (TListView(Sender).Selected <> NIL) then
begin
BeginInternalDrag(TListView(Sender).Selected, Image1.Bitmap);
end;
end;
Bu daha başlangıç, sınıf haline gelince hedefiniz bu aşağıdaki gibi style, item üzerinde butonlar, multidrag/drop, taşıma vb. olacaktır.
FMX içinde ListView zorunluluğunuz da yok bir süre sonra yerine ListBox kullanmak isteyebilirsiniz.

@
mrmarman Allah razı olsun, Tecrübenize sonsun saygı duyuyorum. Hakkınızı ödeyemem.
Kendimce forumdaki bazı paylaşılan bazı kodları ve sizin kodlarınızı bir araya getirerek çözmeye çalışıyorum. Kısmen güzel yol aldım fakat 2 konuda sıkıntı yaşıyorum.
1. Faklı listviewde taşıma sırasında aldığım adres hatası:
First chance exception at $0096FABD. Exception class $C0000005 with message 'access violation at 0x0096fabd: read of address 0x00000000'
2. ise aynı listviewde içinde taşıma sırasında eski satırı silmeyi beceremedim.
procedure TForm1.ListView1DragDrop(Sender: TObject; const Data: TDragObject; const Point: TPointF);
var
Obj: IControl;
AItem: TListViewItem;
I, ImgIndex, Index: Integer;
ObjImgName, ObjName, ObjData: String;
begin
Obj := ObjectAtPoint(Screen.MousePos);
if Obj <> Nil then
begin
Index := GetIndexAtPos(TListView(Sender), Point);
if Index <> -1 then
begin
// showmessage(TListView(Sender).Name);
AItem := TListViewItem(TListView(Sender).Selected); // Seçilen satırın bilgilerini alıyorum
TListView(Sender).Items.Insert(Index); // Insert yapılacak satır no
for I := 0 to Pred(AItem.Objects.Count) - 1 do
begin
if AItem.Objects[I] is TListItemImage then // Image ise bilgileri integer olarak alıyorum
begin
ObjImgName := AItem.Objects[I].Name;
ImgIndex := TListItemImage(AItem.Objects[I]).ImageIndex;
TListView(Sender).Items[Index].Data[ObjImgName] := ImgIndex;
end
else
begin
ObjName := AItem.Objects[I].Name;
ObjData := AItem.Objects[I].Data.ToString;
TListView(Sender).Items[Index].Data[ObjName] := ObjData;
end;
end;
end;
end;
end;
Aramızda kalsın, Nedense lisxbosı sevemedim
Aynı işlemi orangeui listbox ile yapmaya çalışıyorum. Ama bir türlü mantığını kavrayamadım.
Yapmak istediğim şey bir liste içindeki elemanın yerini değiştirmek. Bu işlem için item in Move diye bir özelliği var. Kod ile istediğim item tek satırda yer değiştirebiliyorum.
mesela şunun gibi
lstPersonel.Prop.Items.Move(0, 3);
Fakat aynı işlemi sürükle bırak ile yapmak istiyorum. Bunu bir türlü başaramadım.
Üzerinde çalıştığım örnek uygulama aşağıda. yardımcı olabilir misiniz.