Ir para conteúdo
Fórum Script Brasil
  • 0

Simulando Um Dbchecklistbox


Micheus

Pergunta

Na paleta DataControls do Delphi não existe um componente DBCheckListBox que nos permita gravar uma seleção de itens num determinado campo de uma tabela.

Ao tentar ajudar na solução desta questão neste post do colega Carlos Rocha, verifiquei que era um questionamento que já existia por aí, mas sem resposta. Resolvi então colocar nesta sessão (para que possa mais facilmente ser consultada por outros colegas), um mini-tutorial de como simular um DBCheckListBox a partir de um simples CheckListBox. (o código completo está disponível para download no final deste post)

Primeiramente, vamos observar como o "componente" deveria operar:

- Ao ser posicionado um registro, o CheckListBox deve mostrar marcado os itens que estão gravados no campo apropriado;

- Ao marcarmos ou desmarcarmos um item, isto deveria se refletir no campo sendo editado, onde o nº da posição marcada seria armazenado; Sem esquecer de que, se não estiver em modo edição, devemos verificar se o DataSource está configurado para AutoEdit e então pôr o dataset em modo edição.

Estarei utilizando a gravação do índice que aponta para o item marcado, mas poderíamos gravar o texto do item selecionado. O procedimento seria semelhante. A vantagem sobre utilizar um ou outro fica a critério de cada um.

O componente CheckListBox armazena a informação sobre qual item está marcado na propriedade Checked. Esta propriedade é um array com o nº de posições igual ao nº de itens configurados na lista.

Vamos, então, precisar criar um procedimento que possa ler os itens marcados e montar uma string com este valor para que a mesma possa ser gravada no banco:

...
implementation
{$R *.dfm}

const
  Delimitador = ',';

// Este procedimento é responsável por ler o valor gravado
// no campo da tabela e mostrá-lo no CheckListBox
procedure TForm1.PopulaCheckListBox;
var
  Idx :Integer;
  OpcStr :string;
begin
 // limpa seleção
  for Idx := 0 to CheckListBox1.Count -1 do
    CheckListBox1.Checked[Idx] := False;

  OpcStr := Table1Opcao_PrazoNum.AsString;
  while OpcStr <> '' do
  begin
    Idx := Pos(Delimitador, OpcStr);
   // não encontrar o delimitador, significa que o
   // resto da string contém o último valor
    if Idx = 0 then
     // neste caso, marcamos posição como posterior ao último caracter
      Idx := Length(OpcStr) +1;
   // Marca como selecionado o item lido
    CheckListBox1.Checked[StrToInt(Copy(OpcStr, 1, Idx -1))] := True;
   // elimina o item já processado da lista - em OpsStr
    Delete(OpcStr, 1, Idx);
  end;
end;
Para que ao movimentarmos a posição do registro na tabela, mais facilmente observado quando utilizamos DBGrid para mostrar os dados na mesma tela em que cadastramos, nós utilizaremos o evento OnDataChange do componente TDataSource que está ligado aos componentes de edição (no nosso caso, também será o mesmo que o do DBGrid). Este evento ocorre a cada modificação de um campo do dataset, então deve ser utilizado com moderação. Nós só atualizaremos a lista, a partir do registro atualmente selecionado, somente quando o dataset estiver no modo visualização (dsBrowse):
procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
begin
 // vamos manipular a lista apenas no modo exibição
  if (Sender as TDataSource).State = dsBrowse then
    PopulaCheckListBox;
end;
Nosso próximo objetivo é que ao marcarmos/desmarcarmos um item, o campo seja atualizado. Utilizaremos o evento OnClickCheck do componente CheckListBox. Este evento ocorre justamente nestas situações:
procedure TForm1.CheckListBox1ClickCheck(Sender: TObject);
var
  Idx :Integer;
begin
 // verificamos se é possível colocar a tabela em modo 
 // edição apenas click direto sobre a lista
  if DataSource1.AutoEdit then
    DataSource1.Edit
  else
    Exit;
 // o campo pode ser limpo em qualquer situação, pois, se for o caso,
 // será novamente prenchido com os valores atuais. Se cancel for
 // utilizando, as informações não serão perdidas

  Table1Opcao_PrazoNum.Clear;
 // *** ilustrando como seria se gravássemos o texto ao invés do índice
 // Table1Opcao_PrazoStr.Clear;
 // verifica para cada elemento da lista, se algum está marcado
  for Idx := 0 to CheckListBox1.Count -1 do
  begin
   // apenas se estiver marcado contatena no campo
    if CheckListBox1.Checked[Idx] then
    begin
      Table1Opcao_PrazoNum.AsString := Table1Opcao_PrazoNum.AsString + IntToStr(Idx) +Delimitador;
     // *** ilustrando como seria se gravássemos o texto ao invés do índice
     // Table1Opcao_PrazoStr.AsString := Table1Opcao_PrazoStr.AsString + CheckListBox1.Items[Idx] +Delimitador;
    end;
  end;
 // retira o delimitador que fica sobrando no final
  Table1Opcao_PrazoNum.AsString := Copy(Table1Opcao_PrazoNum.AsString, 1, Length(Table1Opcao_PrazoNum.AsString) -1);
 // *** ilustrando como seria se gravássemos o texto ao invés do índice
 // Table1Opcao_PrazoStr.AsString := Copy(Table1Opcao_PrazoStr.AsString, 1, Length(Table1Opcao_PrazoStr.AsString) -1);
end;
No caso de optar por gravar o texto e não o índice, basta que nas linhas do código acima sejam suprimidas as que contém Opcao_PrazoNum e sejam retirados os comentários das que contém Opcao_PrazoStr. Já a procedure PopulaCheckListBox deve ser substituída pelo código abaixo:
procedure TForm1.PopulaCheckListBox;
var
  Idx :Integer;
  OpcStr :string;
begin
 // limpa seleção
  for Idx := 0 to CheckListBox1.Count -1 do
    CheckListBox1.Checked[Idx] := False;

  OpcStr := Table1Opcao_PrazoStr.AsString;
  while OpcStr <> '' do
  begin
    Idx := Pos(Delimitador, OpcStr);
   // não encontrar o delimitador, significa que o
   // resto da string contém o último valor
    if Idx = 0 then
     // neste caso, marcamos posição como posterior ao último caracter
      Idx := Length(OpcStr) +1;
   // Marca como selecionado o item lido
    if CheckListBox1.Items.IndexOf(Copy(OpcStr, 1, Idx -1)) >= 0 then
      CheckListBox1.Checked[CheckListBox1.Items.IndexOf(Copy(OpcStr, 1, Idx -1))] := True;
   // elimina o item já processado da lista - em OpsStr
    Delete(OpcStr, 1, Idx);
  end;
end;

Espero que consigam ajustar às suas necessidades. O exemplo está em anexo, se houver problemas também pode ser baixado deste link.

Abraços

DBCheckListBox.zip

Link para o comentário
Compartilhar em outros sites

0 respostass a esta questão

Posts Recomendados

Até agora não há respostas para essa pergunta

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,4k
×
×
  • Criar Novo...