AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79554797
Accepted
S.Nieshant
S.Nieshant
Asked: 2025-04-04 16:08:24 +0800 CST2025-04-04 16:08:24 +0800 CST 2025-04-04 16:08:24 +0800 CST

Como comunicar entre usercontrol e mainVM

  • 772

Eu desenvolvi um aplicativo WPF que consiste em uma janela principal e dois controles de usuário. O primeiro controle de usuário contém um botão, e o segundo controle de usuário tem uma caixa de texto. A janela principal inclui um DataGrid.

Preciso configurar para que, quando eu inserir um valor na caixa de texto no segundo controle de usuário e clicar no botão no primeiro controle de usuário, o valor da caixa de texto seja adicionado ao DataGrid na janela principal.

Como posso conseguir isso?

Primeiro controle do usuário:

<UserControl  ....>
  <Grid>
    <Button x:Name="btnAddDetails" Content="Add details" Width="170" Height="60" Click="btnAddDetails_Click"/>
  </Grid>
</UserControl>

Segundo controle do usuário:

<UserControl  ....>
  <StackPanel>
    <TextBox x:Name="txtName"/>
    <TextBox x:Name="txtDesc"/>
    <CheckBox x:Name="chkIsActive" Content="IsActive"/>
  </StackPanel>
</UserControl>
c#
  • 1 1 respostas
  • 49 Views

1 respostas

  • Voted
  1. Best Answer
    Chami Mohammed
    2025-04-04T22:01:08+08:002025-04-04T22:01:08+08:00

    Existem duas maneiras de desenvolver aplicativos em WPF: o padrão code-behind e o MVVM (Model, View, ViewModel), que é o recomendado.

    Vou mostrar a você um passo a passo simples sobre como criar o que você deseja usando o padrão MVVM (maneira recomendada):

    <UserControl  ....>
      <Grid Margin="10">
        <Button
            Padding="10,5"
            Command="{Binding AddUserCommand}"
            Content="Add User" />
    </Grid>
    </UserControl>
    
    <UserControl ...>
      <Grid Margin="10">
        <StackPanel>
            <Label Content="Name:" />
            <TextBox Margin="0,0,0,10" Text="{Binding CurrentUser.Name, UpdateSourceTrigger=PropertyChanged}" />
    
            <Label Content="Description:" />
            <TextBox Margin="0,0,0,10" Text="{Binding CurrentUser.Description}" />
    
            <CheckBox
                Margin="0,0,0,10"
                Content="Is Active"
                IsChecked="{Binding CurrentUser.IsActive}" />
        </StackPanel>
    </Grid>
    </UserControl>
    

    2- Crie o Modelo de Usuário:

    public class User : INotifyPropertyChanged
        {
            private string _name;
            private string _description;
            private bool _isActive;
    
            public string Name
            {
                get => _name;
                set
                {
                    if (_name != value)
                    {
                        _name = value;
                        OnPropertyChanged();
                    }
                }
            }
    
            public string Description
            {
                get => _description;
                set
                {
                    if (_description != value)
                    {
                        _description = value;
                        OnPropertyChanged();
                    }
                }
            }
    
            public bool IsActive
            {
                get => _isActive;
                set
                {
                    if (_isActive != value)
                    {
                        _isActive = value;
                        OnPropertyChanged();
                    }
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    

    3- Crie a classe RelayCommand para manipular o clique do botão Adicionar Usuário:

    public class RelayCommand : ICommand
        {
            private readonly Action<object> _execute;
            private readonly Func<object, bool> _canExecute;
    
            public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
            {
                _execute = execute ?? throw new ArgumentNullException(nameof(execute));
                _canExecute = canExecute;
            }
    
            public event EventHandler CanExecuteChanged
            {
                add { CommandManager.RequerySuggested += value; }
                remove { CommandManager.RequerySuggested -= value; }
            }
    
            public bool CanExecute(object parameter)
            {
                return _canExecute == null || _canExecute(parameter);
            }
    
            public void Execute(object parameter)
            {
                _execute(parameter);
            }
        }
    

    4- Adicione o MainVM:

    public class MainVM : INotifyPropertyChanged
        {
            private User _currentUser;
    
            public MainVM()
            {
                Users = new ObservableCollection<User>();
                CurrentUser = new User();
                AddUserCommand = new RelayCommand(AddUser, CanAddUser);
            }
    
            public ObservableCollection<User> Users { get; }
    
            public User CurrentUser
            {
                get => _currentUser;
                set
                {
                    if (_currentUser != value)
                    {
                        _currentUser = value;
                        OnPropertyChanged();
                    }
                }
            }
    
            public RelayCommand AddUserCommand { get; }
    
            private bool CanAddUser(object obj)
            {
                return !string.IsNullOrWhiteSpace(CurrentUser.Name);
            }
    
            private void AddUser(object obj)
            {
                Users.Add(new User
                {
                    Name = CurrentUser.Name,
                    Description = CurrentUser.Description,
                    IsActive = CurrentUser.IsActive
                });
    
                CurrentUser = new User();
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    

    5- Agora no arquivo xaml da MainWindow adicione estes dois namespaces:

    nota: veja que adicionei o ViewModel na pasta ViewModels e o mesmo para o controle do usuário, embora seja um aplicativo simples que usei apenas para organizar meus arquivos.

    
    xmlns:viewmodels="clr-namespace:SimpleWpfApp.ViewModels"
    xmlns:views="clr-namespace:SimpleWpfApp.UserControls"
    

    5.1- então utilize os user controls criados (no mesmo arquivo xaml):

    <Window.DataContext>
        <viewmodels:MainVM />
    </Window.DataContext>
    
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    
        <views:FillUserDataUserControl Grid.Row="0" />
    
        <views:ButtonUserControl Grid.Row="1" />
    
        <DataGrid
            Grid.Row="2"
            Margin="0,10,0,0"
            AutoGenerateColumns="False"
            IsReadOnly="True"
            ItemsSource="{Binding Users}">
            <DataGrid.Columns>
                <DataGridTextColumn
                    Width="*"
                    Binding="{Binding Name}"
                    Header="Name" />
                <DataGridTextColumn
                    Width="2*"
                    Binding="{Binding Description}"
                    Header="Description" />
                <DataGridCheckBoxColumn
                    Width="*"
                    Binding="{Binding IsActive}"
                    Header="Is Active" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
    

    Nota: o exemplo foi testado antes de ser escrito, você pode encontrá-lo aqui: https://github.com/amuza2/100DaysOfCode/tree/main/Day93/WpfApp1/SimpleWpfApp

    Explicando algumas ideias principais:
    1- Vinculação de dados entre View (controle de usuário) e ViewModel (MainVM), como no FillUserDataUserControl, Text = "{Binding CurrentUser.Name}"que cria uma vinculação entre a propriedade Text da caixa de texto e a CurrentUser.Namepropriedade no ViewModel (MainVM).

    2- INotifyPropertyChanged : Tanto o modelo User quanto o MainViewModel implementam essa interface, que é crucial para a vinculação bidirecional. Quando uma propriedade muda, o PropertyChangedevento é levantado por meio do OnPropertyChanged()método, alertando a UI para atualizar.

    3- DataContext : Em MainWindow.xaml, a linha <Window.DataContext><viewmodels:MainVM /></Window.DataContext>estabelece o ViewModel como a fonte de dados para todas as ligações na janela e seus controles filhos.
    Este sistema de ligação permite alterações na UI para atualizar o ViewModel (e vice-versa) sem escrever manipuladores de eventos explícitos e código de atualização da UI.

    4- No ButtonUserControl.xaml, Command="{Binding AddUserCommand}"vincule a propriedade Command do botão à propriedade AddUserCommand no ViewModel (MainVM).

    • A RelayCommandclasse implementa a ICommandinterface, que define o contrato para comandos no WPF.

    O Commandmanager no RelayCommand se conecta ao CommandManager do WPF, que chama automaticamente CanExecute quando os estados de entrada mudam (como quando o texto é inserido na caixa de texto Nome).

    5- Diferentemente do List<T>, o ObservableCollection implementa INotifyCollectionChanged, que gera eventos quando itens são adicionados, removidos ou quando a coleção muda, o que significa que quando você chama Users.Add(newUser)o ViewModel, o ObservableCollection gera automaticamente o evento CollectionChanged, que o DataGrid escuta, o que significa que novamente o DataGrid é atualizado automaticamente para mostrar o novo item sem exigir nenhum código de atualização manual 🥳.

    Se usássemos uma lista normal, adicionar itens não atualizaria automaticamente a interface do usuário.

    você pode dizer que é muito para um aplicativo simples que tem poucos controles, você está certo, mas o MVVM brilha quando você cria projetos de médio a grande porte.

    • 1

relate perguntas

  • Polly DecorrelatedJitterBackoffV2 - como calcular o tempo máximo necessário para concluir todas as novas tentativas?

  • Wpf. Role o DataGrid dentro do ScrollViewer

  • A pontuação que ganhei na página do jogo com .NET MAUI MVVM não é visível em outras páginas. Como posso manter os dados de pontuação no dispositivo local

  • Use a hierarquia TreeView com HierarchicalDataTemplate de dentro de um DataTemplate

  • Como posso melhorar essa interface de validação no .NET?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve