I realize this is a resurrection of an old question, but I had a very hard time finding a solution to this issue and wanted to try to help others who may need/want something quickly. I hope my search skills didn't fail me and I'm not posting an answer that is already well documented somewhere else. I pretty much just used Astur Iano's post as a guide to complete this.
Basically the idea is that I fill a temporary table with related records in a cardpart page by using the related table's id. Please forgive any typos I converted from a custom table to Item to make it more generic.
Temporary Table
table XXXXXX MediaSetViewer
{
DataClassification = ToBeClassified;
TableType = Temporary;
fields
{
field(1; Index; Integer)
{
Caption = 'Index';
}
field(2; ItemNo; Code[20])
{
Caption = 'Item No.';
}
field(3; Media; Media)
{
Caption = 'Media';
}
field(4; CreatedOn; DateTime)
{
Caption = 'Created On';
}
field(5; CreatedBy; Text[100])
{
Caption = 'Created By';
}
field(6; Description; Text[250])
{
Caption = 'Description';
}
}
keys
{
key(PK; Index, ItemNo)
{
Clustered = true;
}
}
fieldgroups
{
fieldgroup(Brick; Media, Description, CreatedOn, CreatedBy)
{
}
}
}
CardPart
page XXXXXX Pictures
{
PageType = CardPart;
SourceTable = MediaSetViewer;
layout
{
area(Content)
{
field(Count; Rec.Count)
{
ApplicationArea = All;
Caption = 'Number of Pictures';
Style = StrongAccent;
}
field(Media; Rec.Media)
{
ApplicationArea = All;
}
/*group(Description)
{
// Can use only when the photo is uploaded but because
// tenant media is not editable no need to display
field(Desc; Rec.Description)
{
ApplicationArea = All;
MultiLine = true;
ShowCaption = false;
}
}*/
field(CreatedBy; Rec.CreatedBy)
{
ApplicationArea = All;
Visible = false;
}
field(CreatedOn; Rec.CreatedOn)
{
ApplicationArea = All;
Visible = false;
}
field(ItemNo; Rec.ItemNo)
{
ApplicationArea = All;
Visible = false;
}
field(Index; Rec.Index)
{
ApplicationArea = All;
Visible = false;
}
}
}
actions
{
area(Processing)
{
action("Next")
{
ApplicationArea = All;
Image = NextRecord;
Visible = navigationVisible;
trigger OnAction()
var
ct: Integer;
steps: Integer;
begin
ct := Rec.Count;
if Rec.Next(1) = 0 then
steps := Rec.Next((ct * -1) 1); //return to first
reloadRecords := false;
CurrPage.Update(false);
end;
}
action("Previous")
{
ApplicationArea = All;
Image = PreviousRecord;
Visible = navigationVisible;
trigger OnAction()
var
ct: Integer;
steps: Integer;
begin
ct := Rec.Count;
if Rec.Next(-1) = 0 then
steps := Rec.Next(ct); //Go to last.
end;
}
/* action("Edit Description")
{
//Because Tenant Media isn't editable disabled
ApplicationArea = All;
Image = Edit;
Visible = exportEnabled;
trigger OnAction()
begin
editPhotoDesc();
end;
} */
action(Import)
{
ApplicationArea = All;
Enabled = importEnabled;
Image = Import;
trigger OnAction()
begin
ImportMediaSet();
end;
}
action(Export)
{
ApplicationArea = All;
Image = Export;
Enabled = exportEnabled;
trigger OnAction()
begin
ExportMediaSet();
end;
}
action(Delete)
{
ApplicationArea = All;
Image = Delete;
Enabled = deleteEnabled;
trigger OnAction()
begin
RemoveFromMediaSet();
end;
}
}
}
trigger OnAfterGetCurrRecord()
begin
LoadRelatedRecords();
end;
local procedure LoadRelatedRecords()
var
recMediaSet: Record "Tenant Media Set";
recMedia: Record "Tenant Media";
recItem: Record Item;
i: Integer;
res: Boolean;
begin
//Check to see if the temp table needs repopulated
if (itemNo = Rec.ItemNo) and (not reloadRecords) then
exit;
itemNo := Rec.ItemNo;
reloadRecords := false;
//use the SubPageLink fields to get record
if not recItem.Get(Rec.ItemNo) then
exit;
for i := 1 to recItem.Picture.Count do begin
if not recMedia.Get(recItem.Picture.Item(i)) then
break;
Rec.Init();
Rec.ItemNo := recItem."No.";
Rec.Description := recMedia.Description;
Rec.CreatedBy := recMedia."Creating User";
Rec.CreatedOn := recMedia.SystemCreatedAt;
Rec.Index := i;
recMediaSet.Get(recItem.Picture.MediaId, recItem.Picture.Item(i));
Rec.Media := recMediaSet."Media ID";
res := Rec.Insert();
end;
navigationVisible := Rec.Count > 1;
exportEnabled := Rec.Count > 0;
importEnabled := true;
deleteEnabled := exportEnabled and importEnabled;
end;
local procedure ImportMediaSet()
var
recItem: Record Item;
mediaInStream: InStream;
fromFileName: Text;
mediasetId: Guid;
desc: Text;
begin
if UploadIntoStream('Choose Picture', '', 'Image Files |*.jpg;*.jpeg;*.jpe;*.png;*.bmp', fromFileName, mediaInStream) then begin
recItem.Get(Rec.ItemNo);
/*
// Used to get a description for the media, however, because
// it cannot be edited afterwards, better to remove the
// capability.
Clear(lti);
lti.SetText('', 250);
lti.Caption := 'Photo Description';
if lti.RunModal() = Action::OK then
desc := lti.GetText()
else*/
desc := FromFileName;
mediasetId := recItem.Picture.ImportStream(mediaInStream, desc);
recItem.Modify(true);
reloadRecords := true;
LoadRelatedRecords(); //repopulate the temp table so that the new media displays
end;
end;
local procedure ExportMediaSet()
var
recItem: Record Item;
imgInStream: InStream;
imgFilename: Text;
recMedia: Record "Tenant Media";
begin
if not recItem.Get(Rec.ItemNo) then
exit;
if recItem.Picture.Count = 0 then
Error('No picture stored');
if recMedia.Get(recItem.Picture.Item(Rec.Index)) then begin
recMedia.CalcFields(Content);
if recMedia.Content.HasValue() then begin
imgFilename := Rec.ItemNo '-' '_Image' format(Rec.Index) extProcedures.GetImgFileExt(recMedia);
recMedia.Content.CreateInStream(imgInStream);
DownloadFromStream(imgInStream, 'Export File', '', '', imgFilename);
end;
end;
end;
local procedure RemoveFromMediaSet()
var
recItem: Record Item;
mediaGuid: Guid;
confirm: Label 'Are you sure you want to remove picture ID: %1, Description: %2?';
removed: Label 'Picture ID: %1, Description: %2, successfully removed.';
picDesc: Text;
begin
if not recItem.Get(Rec.ItemNo) then
exit;
if recItem.Picture.Count = 0 then
Error('No picture stored');
mediaGuid := recItem.Picture.Item(Rec.Index);
picDesc := Rec.Description;
if Dialog.Confirm(confirm, false, mediaGuid, picDesc) then begin
if recItem.Picture.Remove(mediaGuid) then begin
delRes := Rec.Delete();
Message(removed, medGuid, picDesc);
//Reload the records to reindex media and update page
reloadRecords := true;
LoadRelatedRecords();
CurrPage.Update(false);
end
else
Error('Failed to remove picture ID: %1, Description: %2.', mediaGuid, picDesc);
end;
end;
/*
//Removed because premissions denied to edit Tenant Media table
local procedure EditPhotoDesc()
var
recItem: Record Item;
recMedia: Record "Tenant Media";
begin
if not recItem.Get(Rec.ItemNo) then
exit;
if recItem.Picture.Count = 0 then
Error('No picture stored');
recMedia.Get(recItem.Picture.Item(Rec.Index));
Clear(lti);
lti.SetText(recMedia.Description, 250);
lti.Caption := 'Photo Description';
if lti.RunModal() = Action::OK then begin
recMedia.Description := lti.GetText();
recMedia.Modify(false);
end;
end; */
var
extProcedures: Codeunit Extension_Procedures;
lti: Page LongTextInput; // just a dialog page with a single multiline text box
itemNo: Code[20];
reloadRecords: Boolean;
navigationVisible: Boolean;
exportEnabled: Boolean;
importEnabled: Boolean;
deleteEnabled: Boolean;
}
Create the factbox picture link using;
SubPageLink = ItemNo = field("No.");