using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Reflection; using System.Windows.Controls.Primitives; namespace BD_empresa { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { private string? _lastClickedCellText; public MainWindow() { InitializeComponent(); // Caminho do banco de dados Access string accessDbPath = "X:\\Middle\\Informativo Setorial\\Modelo Word\\BD1_dados cadastrais e faturas.accdb"; var accessService = new Data.AccessService($"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={accessDbPath};Jet OLEDB:Database Password=gds21"); DataContext = new ViewModels.MainWindowViewModel(accessService); } /// /// Captura texto quando clica com o botão esquerdo /// private void UnidadesListView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (sender is ListView lv) { var pt = e.GetPosition(lv); RecordCellTextFromPoint(lv, pt); } } /// /// Seleciona o item clicado com o botão direito e captura o texto da célula clicada /// private void UnidadesListView_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { if (sender is ListView lv) { var pt = e.GetPosition(lv); var hit = VisualTreeHelper.HitTest(lv, pt); var dep = hit?.VisualHit; if (dep == null) return; // Seleciona o item clicado var lvi = FindAncestor(dep); if (lvi != null) lvi.IsSelected = true; // Se certo elemento TextBox foi clicado, foca ele (para permitir seleção/Ctrl+C) var tbx = FindAncestor(dep) ?? FindDescendant(dep); tbx?.Focus(); RecordCellTextFromPoint(lv, pt); } } private void UnidadesListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { _lastClickedCellText = null; } /// /// Executado quando o usuário pressiona Ctrl+C /// private void CopyCommand_Executed(object sender, ExecutedRoutedEventArgs e) { // sender normalmente é o ListView (porque definimos o CommandBinding nele). var lv = sender as ListView ?? UnidadesListView; CopyTextFromListView(lv); } /// /// Executado pelo MenuItem do ContextMenu /// private void CopyMenu_Click(object sender, RoutedEventArgs e) { CopyTextFromListView(UnidadesListView); } /// /// Copia para o clipboard com base no último texto clicado ou em fallback (primeira coluna) /// private void CopyTextFromListView(ListView? listView) { if (listView == null) return; // 1) se o usuário clicou previamente em uma célula (direito/esquerdo), usamos esse texto if (!string.IsNullOrEmpty(_lastClickedCellText)) { try { Clipboard.SetText(_lastClickedCellText); } catch (Exception ex) { MessageBox.Show($"Erro ao copiar para o clipboard: {ex.Message}", "Erro", MessageBoxButton.OK, MessageBoxImage.Error); } return; } // 2) fallback: usa a primeira coluna (se houver) do item selecionado if (listView.SelectedItem is Data.UnidadeSmart unidade) { var gv = listView.View as GridView; if (gv?.Columns.Count > 0) { var firstCol = gv.Columns[0]; // tenta obter o DisplayMemberBinding.Path if (firstCol.DisplayMemberBinding is System.Windows.Data.Binding b && !string.IsNullOrEmpty(b.Path?.Path)) { var prop = unidade.GetType().GetProperty(b.Path.Path, BindingFlags.Public | BindingFlags.Instance); if (prop != null) { var value = prop.GetValue(unidade)?.ToString() ?? string.Empty; try { Clipboard.SetText(value); } catch (Exception ex) { MessageBox.Show($"Erro ao copiar para o clipboard: {ex.Message}", "Erro", MessageBoxButton.OK, MessageBoxImage.Error); } return; } } // se não tiver DisplayMemberBinding (ou falhar), tenta buscar visualmente o TextBlock do ListViewItem var lvi = listView.ItemContainerGenerator.ContainerFromItem(unidade) as ListViewItem; var tb = FindDescendant(lvi); if (tb != null) { try { Clipboard.SetText(tb.Text); } catch (Exception ex) { MessageBox.Show($"Erro ao copiar para o clipboard: {ex.Message}", "Erro", MessageBoxButton.OK, MessageBoxImage.Error); } return; } } // 3) fallback final: ToString do objeto try { Clipboard.SetText(unidade?.ToString() ?? string.Empty); } catch (Exception ex) { MessageBox.Show($"Erro ao copiar para o clipboard: {ex.Message}", "Erro", MessageBoxButton.OK, MessageBoxImage.Error); } } } /// /// Faz hit-test em point e tenta achar o TextBlock responsável pela célula clicada; /// grava em _lastClickedCellText. /// private void RecordCellTextFromPoint(ListView listView, Point point) { _lastClickedCellText = null; var hit = VisualTreeHelper.HitTest(listView, point); var dep = hit?.VisualHit; if (dep == null) return; // 1) Procura TextBox (nossa célula agora é TextBox readonly) var tbx = FindAncestor(dep) ?? FindDescendant(dep); if (tbx != null) { // se houver seleção, prioriza a seleção if (!string.IsNullOrEmpty(tbx.SelectedText)) _lastClickedCellText = tbx.SelectedText; else _lastClickedCellText = tbx.Text; return; } // 2) Procura TextBlock (fallback) var tblock = FindAncestor(dep) ?? FindDescendant(dep); if (tblock != null) { _lastClickedCellText = tblock.Text; return; } // 3) Fallback: procura container e, dentro dele, tenta TextBox primeiro, depois TextBlock DependencyObject? container = FindAncestor(dep); container ??= FindAncestor(dep); if (container != null) { var innerTbx = FindDescendant(container); if (innerTbx != null) { _lastClickedCellText = !string.IsNullOrEmpty(innerTbx.SelectedText) ? innerTbx.SelectedText : innerTbx.Text; return; } var innerTblock = FindDescendant(container); if (innerTblock != null) { _lastClickedCellText = innerTblock.Text; return; } } // 4) último recurso: se um ListViewItem foi selecionado, tenta pegar a primeira coluna via binding (fallback anterior) if (listView.SelectedItem is Data.UnidadeSmart unidade) { var gv = listView.View as GridView; if (gv?.Columns.Count > 0) { var firstCol = gv.Columns[0]; if (firstCol.DisplayMemberBinding is System.Windows.Data.Binding b && !string.IsNullOrEmpty(b.Path?.Path)) { var prop = unidade.GetType().GetProperty(b.Path.Path, BindingFlags.Public | BindingFlags.Instance); if (prop != null) { var value = prop.GetValue(unidade)?.ToString() ?? string.Empty; _lastClickedCellText = value; } } } } } // Helpers (coloque-os se já não existirem): private static T? FindAncestor(DependencyObject? current) where T : DependencyObject { while (current != null) { if (current is T typed) return typed; current = VisualTreeHelper.GetParent(current); } return null; } private static T? FindDescendant(DependencyObject? root) where T : DependencyObject { if (root == null) return null; var queue = new Queue(); queue.Enqueue(root); while (queue.Count > 0) { var node = queue.Dequeue(); var childrenCount = VisualTreeHelper.GetChildrenCount(node); for (int i = 0; i < childrenCount; i++) { var child = VisualTreeHelper.GetChild(node, i); if (child is T found) return found; queue.Enqueue(child); } } return null; } private void Window_Loaded(object sender, RoutedEventArgs e) { txtEmpresaSearch.Focus(); } private void UnidadeListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (sender is ListViewItem listViewItem && listViewItem.Content is Data.UnidadeSmart unidade && !string.IsNullOrWhiteSpace(unidade.Caminho_NFs)) { string? parentDirectory = System.IO.Path.GetDirectoryName(unidade.Caminho_NFs); if (!string.IsNullOrWhiteSpace(parentDirectory)) { try { System.Diagnostics.Process.Start("explorer.exe", parentDirectory); } catch (System.Exception ex) { MessageBox.Show($"Não foi possível abrir a pasta: {ex.Message}", "Erro", MessageBoxButton.OK, MessageBoxImage.Error); } } } } private void UnidadeListView_EnterKeyDown(object sender, KeyEventArgs e) { try { if (e.Key != Key.Enter) { return; } // DataContext do Button será a UnidadeSmart relacionada à linha var lvi = sender as ListViewItem; if (lvi?.Content is not Data.UnidadeSmart unidade) { MessageBox.Show("Não foi possível identificar a unidade.", "Erro", MessageBoxButton.OK, MessageBoxImage.Warning); return; } var caminho = unidade.Caminho_NFs; if (string.IsNullOrWhiteSpace(caminho)) { MessageBox.Show("Não há caminho definido para essa unidade.", "Aviso", MessageBoxButton.OK, MessageBoxImage.Information); return; } string folderToOpen; // Se o caminho for um arquivo (provavelmente um arquivo NFe), abre o diretório pai. if (System.IO.File.Exists(caminho)) { folderToOpen = System.IO.Path.GetDirectoryName(caminho) ?? caminho; } else { // tenta obter diretório do caminho (caso usuário tenha colocado um arquivo inexistente ou caminho parcial) var parent = System.IO.Path.GetDirectoryName(caminho); if (!string.IsNullOrWhiteSpace(parent) && System.IO.Directory.Exists(parent)) folderToOpen = parent; else { MessageBox.Show($"O caminho informado não existe: {caminho}", "Erro", MessageBoxButton.OK, MessageBoxImage.Error); return; } } // Abre o Explorer na pasta encontrada (UseShellExecute = true para abrir paths corretamente) var psi = new System.Diagnostics.ProcessStartInfo { FileName = "explorer.exe", Arguments = $"\"{folderToOpen}\"", UseShellExecute = true }; System.Diagnostics.Process.Start(psi); } catch (System.Exception ex) { MessageBox.Show($"Não foi possível abrir a pasta: {ex.Message}", "Erro", MessageBoxButton.OK, MessageBoxImage.Error); } } private void OpenFolderButton_Click(object sender, RoutedEventArgs e) { try { // DataContext do Button será a UnidadeSmart relacionada à linha var btn = sender as Button; if (btn?.DataContext is not Data.UnidadeSmart unidade) { MessageBox.Show("Não foi possível identificar a unidade.", "Erro", MessageBoxButton.OK, MessageBoxImage.Warning); return; } var caminho = unidade.Caminho_NFs; if (string.IsNullOrWhiteSpace(caminho)) { MessageBox.Show("Não há caminho definido para essa unidade.", "Aviso", MessageBoxButton.OK, MessageBoxImage.Information); return; } string folderToOpen; // Se o caminho for um arquivo (provavelmente um arquivo NFe), abre o diretório pai. if (System.IO.File.Exists(caminho)) { folderToOpen = System.IO.Path.GetDirectoryName(caminho) ?? caminho; } else { // tenta obter diretório do caminho (caso usuário tenha colocado um arquivo inexistente ou caminho parcial) var parent = System.IO.Path.GetDirectoryName(caminho); if (!string.IsNullOrWhiteSpace(parent) && System.IO.Directory.Exists(parent)) folderToOpen = parent; else { MessageBox.Show($"O caminho informado não existe: {caminho}", "Erro", MessageBoxButton.OK, MessageBoxImage.Error); return; } } // Abre o Explorer na pasta encontrada (UseShellExecute = true para abrir paths corretamente) var psi = new System.Diagnostics.ProcessStartInfo { FileName = "explorer.exe", Arguments = $"\"{folderToOpen}\"", UseShellExecute = true }; System.Diagnostics.Process.Start(psi); } catch (System.Exception ex) { MessageBox.Show($"Não foi possível abrir a pasta: {ex.Message}", "Erro", MessageBoxButton.OK, MessageBoxImage.Error); } } } }