Desenvolvimento com WPF: Técnicas e Implementações

  1. Funcionalidade de Paginação

Referência:

Cortagem de dados em datatable C# para obter subset de dados

Uso do DataGrid no WPF






















private void btnAnterior_Click(object sender, RoutedEventArgs e)
{
    int paginaAtual = Convert.ToInt32(tbkPaginaAtual.Text);
    if (paginaAtual == 1)
    {
        MessageBox.Show("Já está na primeira página!");
    }
    else
    {
        int posicaoInicial = (paginaAtual-1 * tamanhoPagina) - tamanhoPagina; 
        var consulta = tabelaDados.Copy().AsEnumerable().Skip(posicaoInicial).Take(tamanhoPagina);
        DataTable novaTabela = new DataTable();
        novaTabela = consulta.CopyToDataTable<DataRow>();
        gradeDados.ItemsSource = novaTabela.DefaultView;
        this.tbkPaginaAtual.Text = (paginaAtual -1).ToString();
    }
    
}

private void btnProximo_Click(object sender, RoutedEventArgs e)
{
    int paginaAtual = Convert.ToInt32(tbkPaginaAtual.Text);
    int totalPaginas = Convert.ToInt32(tbkTotalPaginas.Text);
    if (paginaAtual == totalPaginas)
    {
        MessageBox.Show("Já está na última página!");
    }
    else
    {
        int posicaoInicial = paginaAtual * tamanhoPagina;
        if (tabelaDados.Rows.Count - posicaoInicial < tamanhoPagina)
        {
            var consulta = tabelaDados.Copy().AsEnumerable().Skip(posicaoInicial).Take(tabelaDados.Rows.Count-posicaoInicial);
            DataTable novaTabela = new DataTable();
            novaTabela = consulta.CopyToDataTable<DataRow>();
            gradeDados.ItemsSource = novaTabela.DefaultView;
            this.tbkPaginaAtual.Text = (paginaAtual + 1).ToString();
        }
        else
        {
            var consulta = tabelaDados.Copy().AsEnumerable().Skip(posicaoInicial).Take(tamanhoPagina);
            DataTable novaTabela = new DataTable();
            novaTabela = consulta.CopyToDataTable<DataRow>();
            gradeDados.ItemsSource = novaTabela.DefaultView;
            this.tbkPaginaAtual.Text = (paginaAtual + 1).ToString();
        }
        
    }
}

  1. Criação de DLL para armazenamento de imagens

Adicione um novo projeto, clique com o botão direito no nome do projeto > Propriedades, no seção Aplicação, modifique o tipo de saída do assembly para "Biblioteca de Classes", salve.

Clique com o botão direito em App.XML > Propriedades, mude Ação de Compilação para Page,

Você pode criar uma nova pasta neste projeto para armazenar as imagens.

Finalmente, gere a DLL.

No projeto principal, adicione uma referência, selecione o arquivo DLL gerado.

No XAML do projeto principal, a sintaxe para referenciar imagens:

BIBLIOTECA é o nome da sua DLL, img/proximo.png é o caminho da imagem na DLL

<Image Source="pack://application:,,,/BIBLIOTECA;Componetn/img/proximo.png" Width="18" Height="18"></Image>

  1. Diálogos de cor e fonte no WPF

Referência:

Utilizando diálogos de cor e fonte no WPF

using System.Windows.Forms;
// Diálogo de fonte
FontDialog dialogoFonte = new FontDialog();
var resultado = dialogoFonte.ShowDialog();
if (resultado == System.Windows.Forms.DialogResult.OK)
{
    Debug.WriteLine(dialogoFonte.Font);

    caixaTexto.FontFamily = new FontFamily(dialogoFonte.Font.Name);
    caixaTexto.FontSize = dialogoFonte.Font.Size * 96.0 / 72.0;
    caixaTexto.FontWeight = dialogoFonte.Font.Bold ? FontWeights.Bold : FontWeights.Regular;
    caixaTexto.FontStyle = dialogoFonte.Font.Italic ? FontStyles.Italic : FontStyles.Normal;

    TextDecorationCollection decoracoes = new TextDecorationCollection();
    if (dialogoFonte.Font.Underline) decoracoes.Add(TextDecorations.Underline);
    if (dialogoFonte.Font.Strikeout) decoracoes.Add(TextDecorations.Strikethrough);
    caixaTexto.TextDecorations = decoracoes;

    // Exemplo
    nomeFonte.Text = dialogoFonte.Font.Name.ToString();
    tamanhoFonte.Text = dialogoFonte.Font.Size.ToString();
}

// Diálogo de cor
ColorDialog dialogoCor = new ColorDialog();
var resultado = dialogoCor.ShowDialog();
if (resultado == System.Windows.Forms.DialogResult.OK)
{
    caixaTexto.Foreground = new SolidColorBrush(Color.FromArgb(dialogoCor.Color.A, dialogoCor.Color.R, 
   dialogoCor.Color.G, dialogoCor.Color.B));

   // Exemplo
   corSelecionada.Text = Color.FromArgb(dialogoCor.Color.A, dialogoCor.Color.R, dialogoCor.Color.G, dialogoCor.Color.B).ToString();
}

  1. Quebra automática de texto em controles

1. Usando caracteres de escape
No arquivo XAML:



No arquivo .cs:
this.blocoTexto.Text = "Jack\nTom";

2. Definindo propriedades
Basta configurar TextWrapping = "Wrap" no TextBlock:
Jack|Tom

3. Usando a propriedade InLines com LineBreak

Jack

Tom


  1. Efeitos de sombra em bordas

// Sombra em Border







// Sombra em TextBox






// Sombra em Button






// Sombra em Image






  1. Desenhando linhas



  1. Componente DataGrid


<!-- Grade de dados -->







































// Inicialização
DataTable tabelaPrincipal = new DataTable();
DataColumn colunaImagem = tabelaPrincipal.Columns.Add("imagem", Type.GetType("System.String"));
for (int i = 0; i < tabelaPrincipal.Rows.Count; i++)
{
    if (tabelaPrincipal.Rows[i]["habilitado"].ToString() == "True")
    {
        tabelaPrincipal.Rows[i]["imagem"] = "caminho/imagem1.png";
    }
    else
    {
        tabelaPrincipal.Rows[i]["imagem"] = "caminho/imagem2.png";
    }
}
gradeDados.ItemsSource = tabelaPrincipal.DefaultView;

// Evento de clique no checkbox
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
    CheckBox cb = (CheckBox)sender;
    for(int i = 0; i < tabelaPrincipal.Rows.Count; i++)
    {
        if (tabelaPrincipal.Rows[i]["Etapa"].ToString() == cb.Tag.ToString())
        {
            if (cb.IsChecked == true)
            {
                tabelaPrincipal.Rows[i]["imagem"] = "caminho/imagem1.png";
            }
            else
            {
                tabelaPrincipal.Rows[i]["imagem"] = "caminho/imagem2.png";
            }
        }
    }
}

  1. Navegação entre páginas



// Navegação para uma página
navegador.Navigate(new PaginaDetalhes());

// Voltar para a página anterior
if (navegador.CanGoBack)
{
    navegador.GoBack();
}

// Limpar histórico de navegação
while (navegador.RemoveBackEntry() != null)
{
    // Continua removendo entradas
}

  1. Arrastar e soltar controles



<!-- Conteúdo do controle -->



// Variáveis para controle de arrasto
private bool _estaArrastando = false;
private Point _posicaoInicialMouse;
private Thickness _margemInicial;

private void Controle_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var controle = sender as Border;
    _estaArrastando = true;
    _posicaoInicialMouse = e.GetPosition(areaCanvas);
    _margemInicial = controle.Margin;
    controle.CaptureMouse();
}

private void Controle_PreviewMouseMove(object sender, MouseEventArgs e)
{
    if (_estaArrastando)
    {
        var controle = sender as Border;
        var posicaoAtual = e.GetPosition(areaCanvas);
        var diferenca = posicaoAtual - _posicaoInicialMouse;
        
        controle.Margin = new Thickness(
            _margemInicial.Left + diferenca.X, 
            _margemInicial.Top + diferenca.Y, 
            _margemInicial.Right - diferenca.X, 
            _margemInicial.Bottom - diferenca.Y
        );
    }
}

private void Controle_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
    var controle = sender as Border;
    _estaArrastando = false;
    controle.ReleaseMouseCapture();
    
    // Salvar posição no banco de dados
    SalvarPosicao(controle.Name, controle.Margin);
}

  1. Formatação de texto programaticamente

private void AplicarFormatacaoTexto(Control controle, string nomeFonte, double tamanho, string cor)
{
if (controle.GetType() == typeof(TextBlock))
{
var familiasSistema = Fonts.SystemFontFamilies;
FontFamily familiaFiltrada = null;

foreach (FontFamily familia in familiasSistema)
{
LanguageSpecificStringDictionary nomesFamilia = familia.FamilyNames;
if (nomesFamilia.ContainsKey(XmlLanguage.GetLanguage("pt-br")))
{
if (nomesFamilia.TryGetValue(XmlLanguage.GetLanguage("pt-br"), out var nomeFontePt) &&
nomeFontePt == nomeFonte)
{
familiaFiltrada = familia;
break;
}
}
}

((TextBlock)controle).FontSize = tamanho;
((TextBlock)controle).FontFamily = familiaFiltrada;
((TextBlock)controle).Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString(cor));
}
}

  1. Busca por controles filhos

private void ProcessarControlesFilhos()
{
DependencyObject painelEmpacotador = EncontrarPainelEmpacotador();

if (painelEmpacotador != null)
{
int totalFilhos = VisualTreeHelper.GetChildrenCount(painelEmpacotador);

for (int i = 0; i < totalFilhos; i++)
{
DependencyObject painelWrap = VisualTreeHelper.GetChild(painelEmpacotador, i);
int totalNoWrap = VisualTreeHelper.GetChildrenCount(painelWrap);

for (int j = 0; j < totalNoWrap; j++)
{
DependencyObject canvasFilho = VisualTreeHelper.GetChild(painelWrap, j);

if (canvasFilho is Canvas)
{
ProcessarCanvasFilho((Canvas)canvasFilho);
}
}
}
}
}

private void ProcessarCanvasFilho(Canvas canvas)
{
string nomeCanvas = canvas.Name;
int totalControles = VisualTreeHelper.GetChildrenCount(canvas);

for (int k = 0; k < totalControles; k++)
{
DependencyObject elemento = VisualTreeHelper.GetChild(canvas, k);

if (elemento is Border)
{
ProcessarBordaFilho((Border)elemento, nomeCanvas);
}
}
}

private void ProcessarBordaFilho(Border borda, string nomeCanvas)
{
DependencyObject label = VisualTreeHelper.GetChild(borda, 0);

if (label is Label)
{
Label etiqueta = (Label)label;

if (etiqueta.Name.StartsWith("id"))
{
int id = Convert.ToInt32(etiqueta.Content);
// Processar ID
}

if (etiqutea.Name.StartsWith("pontuacao"))
{
int pontuacao = Convert.ToInt32(etiqueta.Content);
// Processar pontuação
}
}
}

  1. Eventos de duplo clique e perda de foco



private void DuploClique_TextBox(object sender, MouseButtonEventArgs e)
{
    if (FocusManager.GetFocusedElement(this) is TextBox)
    {
        Keyboard.ClearFocus();
        ((TextBox)FocusManager.GetFocusedElement(this)).IsReadOnly = true;
    }
}

  1. Operações básicas de janela










private void Minimizar_Click(object sender, RoutedEventArgs e)
{
    this.WindowState = WindowState.Minimized;
}

private void Maximizar_Click(object sender, RoutedEventArgs e)
{
    this.WindowState = WindowState.Maximized;
}

private void Restaurar_Click(object sender, RoutedEventArgs e)
{
    this.WindowState = WindowState.Normal;
}

private void Fechar_Click(object sender, RoutedEventArgs e)
{
    this.Close();
}

  1. Menu de contexto em botão










private void Novo_Click(object sender, RoutedEventArgs e)
{
    Button botao = (Button)sender;
    botao.ContextMenu.IsOpen = true;
}

  1. Personalização de caixas de mensagem

string mensagem = "Deseja salvar as alterações?";
string titulo = "Editor de Texto";
MessageBoxButton botoes = MessageBoxButton.YesNoCancel;
MessageBoxIcon icone = MessageBoxImage.Warning;
MessageBoxResult resultado;

resultado = MessageBox.Show(mensagem, titulo, botoes, icone, MessageBoxResult.Yes);

  1. Componente Page e navegação



// Navegação entre páginas
navegador.Navigate(new PaginaInicial());

// Limpar histórico ao sair da página
private void Pagina_Unloaded(object sender, RoutedEventArgs e)
{
    if (navegador != null)
    {
        while (navegador.RemoveBackEntry() != null)
        {
            // Continua removendo entradas
        }
    }
}

  1. Alterando cores de fundo programaticamente

private void DefinirCorFundo(Control controle, string corHexadecimal)
{
controle.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString(corHexadecimal));
}

  1. Gráficos de barras

1. Usando LiveCharts














public class ModeloGrafico
{
    public SeriesCollection ColecaoSeries { get; set; }
    public List<int> Valores { get; set; }
    public List<string> Nomes { get; set; }

    public ModeloGrafico()
    {
        InicializarDados();
    }

    private void InicializarDados()
    {
        ColecaoSeries = new SeriesCollection();
        Nomes = new List<string> { "Item 1", "Item 2", "Item 3" };
        Valores = new List<int> { 5, 7, 3 };
        
        var barras = new ColumnSeries
        {
            DataLabels = true,
            LabelsPosition = BarLabelPosition.Perpendicular,
            Title = "Valores",
            Values = new ChartValues<int>(Valores)
        };
        
        ColecaoSeries.Add(barras);
    }
}

2. Gráfico 2D personalizado

public void DesenharGrafico2D(List nomes, List valores)
{
canvasGrafico.Children.Clear();

double alturaCanvas = canvasGrafico.Height;
double maximoValor = valores.Max();

for (int i = 0; i < nomes.Count; i++)
{
double alturaBarra = alturaCanvas * (valores[i] / maximoValor);
StackPanel painel = CriarPainelBarra(70, alturaBarra, i, valores[i], nomes[i]);

Canvas.SetTop(painel, canvasGrafico.Height - painel.Height);
Canvas.SetLeft(painel, 20 + 90 * i);

canvasGrafico.Children.Add(painel);
}
}

private StackPanel CriarPainelBarra(double largura, double altura, int indice, double valor, string nome)
{
StackPanel painel = new StackPanel
{
Height = altura + 100,
Orientation = Orientation.Horizontal
};

TextBlock valorText = new TextBlock
{
Text = valor.ToString(),
Height = 30,
FontSize = 18,
Margin = new Thickness(30, 0, 0, 0),
Foreground = new SolidColorBrush(Colors.White)
};

Rectangle barra = new Rectangle
{
Fill = new SolidColorBrush(ObterCor(indice)),
Height = altura,
Width = largura,
Margin = new Thickness(30, 0, 0, 0),
VerticalAlignment = VerticalAlignment.Top
};

TextBlock nomeText = new TextBlock
{
TextWrapping = TextWrapping.Wrap,
Width = 60,
Height = 100,
FontSize = 18,
Margin = new Thickness(30, 0, 0, 10),
RenderTransform = new SkewTransform(-20, 0),
Foreground = new SolidColorBrush(Colors.White)
};
nomeText.Text = nome;

painel.Children.Add(valorText);
painel.Children.Add(barra);
painel.Children.Add(nomeText);

return painel;
}

  1. Importação e exportação de dados

public bool ExportarParaExcel(DataTable tabela)
{
SaveFileDialog salvarArquivo = new SaveFileDialog();
salvarArquivo.Filter = "Excel (2007-2016)|*.xlsx";

if (salvarArquivo.ShowDialog() != true)
return false;

string extensao = Path.GetExtension(salvarArquivo.FileName);

if (extensao.Equals(".xlsx"))
{
IWorkbook workbook = new XSSFWorkbook();
ISheet sheet = workbook.CreateSheet("Dados");

// Criar cabeçalho
IRow headerRow = sheet.CreateRow(0);
for (int i = 0; i < tabela.Columns.Count; i++)
{
headerRow.CreateCell(i, CellType.String).SetCellValue(tabela.Columns[i].ColumnName);
}

// Preencher dados
for (int i = 0; i < tabela.Rows.Count; i++)
{
IRow dataRow = sheet.CreateRow(i + 1);
for (int j = 0; j < tabela.Columns.Count; j++)
{
dataRow.CreateCell(j, CellType.String)
.SetCellValue(tabela.Rows[i][j]?.ToString() ?? "");
}
}

// Ajustar largura das colunas
for (int i = 0; i < tabela.Columns.Count; i++)
{
sheet.AutoSizeColumn(i);
}

// Salvar arquivo
using (FileStream stream = File.OpenWrite(salvarArquivo.FileName))
{
workbook.Write(stream);
stream.Close();
}

MessageBox.Show("Dados exportados com sucesso!");
return true;
}

return false;
}

  1. Personalização do TabControl

























































<!-- Uso do TabControl personalizado -->

...
...


  1. Manipulação de DataTable

// Adicionar nova linha
DataRow novaLinha = tabela.NewRow();
novaLinha["Nome"] = "Novo Item";
novaLinha["Valor"] = 100;
tabela.Rows.Add(novaLinha);

// Remover linha
tabela.Rows.Remove(linhaARemover);

// Editar célula
linha["Nome"] = "Nome Atualizado";

// Filtrar dados
DataTable tabelaFiltrada = tabela.Select("Valor > 50").CopyToDataTable();

// Ordenar dados
DataTable tabelaOrdenada = tabela.Clone();
tabelaOrdenada.DefaultView.Sort = "Nome DESC";
tabelaOrdenada = tabelaOrdenada.DefaultView.ToTable();

  1. Manipulação de arrays

// Copiar array
int[] arrayOriginal = {1, 2, 3, 4, 5};
int[] arrayCopia = new int[arrayOriginal.Length];
Array.Copy(arrayOriginal, arrayCopia, arrayOriginal.Length);

// Encontrar elementos comuns
string[] array1 = {"A", "B", "C", "D"};
string[] array2 = {"B", "D", "F"};

var elementosComuns = array1.Intersect(array2).ToArray();
var elementosDiferentes = array1.Where(x => !array2.Contains(x)).ToArray();

  1. Definindo imagem de fundo programaticamente

// Método 1
fundo.Background = new ImageBrush
{
ImageSource = new BitmapImage(new Uri("caminho/imagem.jpg", UriKind.RelativeOrAbsolute))
};

// Método 2
ImageBrush brushFundo = new ImageBrush();
brushFundo.ImageSource = new BitmapImage(new Uri("caminho/imagem.jpg"));
painel.Background = brushFundo;

Tags: WPF .NET C# XAML Interface Gráfica

Publicado em 6-6 22:48 por Thomas