繁体   English   中英

在不关闭新视图 (WPF MVVM) CRUD 的情况下将数据添加到 Datagrid

[英]Add Data to Datagrid Without Closing new View (WPF MVVM) CRUD

我是 MVVM 的新手,我似乎无法找到我的问题的答案..

我有 2 个视图(Caixa 和 CaixaDetalhes),在 Caixa 视图中我有一个显示所有 Caixas 的数据网格,在第二个视图中显示详细信息,用户可以“CRUD”,但我不想在更新或添加时关闭视图与对话结果。

我的观点:

AssistenciasCaixas:

<DataGrid x:Name="dgCaixas" Grid.Row="1" Style="{StaticResource DataGridResultados}" ItemsSource="{Binding Caixas}" SelectedItem="{Binding CaixaSelecionado}" RowHeight="25" Background="White" >
           <DataGrid.Columns>
               <DataGridTextColumn Header="Id" Visibility="Hidden" Binding="{Binding Id}"/>
               <DataGridTextColumn Header="PostoID" Visibility="Hidden" Binding="{Binding Posto.ID}"/>
               <DataGridTextColumn Header="IdUtilizador" Visibility="Hidden" Binding="{Binding IdUtilizador}"/>
               <DataGridTextColumn Header="Posto" Width="200" Binding="{Binding Posto.Descricao}" CanUserReorder="False" CanUserResize="False" CanUserSort="False" FontSize="15" IsReadOnly="True"/>
               <DataGridTextColumn Header="Data Caixa" Width="90" Binding="{Binding DataCaixa,StringFormat={}\{0:dd/MM/yyyy\}}" CanUserReorder="False" CanUserResize="False" CanUserSort="False" FontSize="15" IsReadOnly="True"/>
               <DataGridTextColumn Header="Data Eliminado" Width="100" Binding="{Binding DataEliminado, StringFormat={}\{0:dd/MM/yyyy\}}" CanUserReorder="False" CanUserResize="False" CanUserSort="False" FontSize="15" IsReadOnly="True"/>
               <DataGridTextColumn Header="Motivo" Width="*" Binding="{Binding Motivo}" CanUserReorder="False" CanUserResize="False" CanUserSort="False" FontSize="15" IsReadOnly="True"/>
               <DataGridTextColumn Header="Nº Caixa" Width="70" Binding="{Binding NumCaixa}" CanUserReorder="False" CanUserResize="False" CanUserSort="False" FontSize="15" IsReadOnly="True"/>
               <DataGridTextColumn Header="Exportado" Width="100" Binding="{Binding Exportado}" CanUserReorder="False" CanUserResize="False" CanUserSort="False" FontSize="15" IsReadOnly="True">
                   <DataGridTextColumn.ElementStyle>
                       <Style TargetType="TextBlock">
                           <Setter Property="HorizontalAlignment" Value="Center" />
                       </Style>
                   </DataGridTextColumn.ElementStyle>
               </DataGridTextColumn>
               <DataGridTextColumn Header="Observações" Width="200" Binding="{Binding Obs}" CanUserReorder="False" CanUserResize="False" CanUserSort="False" FontSize="15" IsReadOnly="True"/>
               <DataGridTextColumn Header="Utilizador" Visibility="Hidden" Binding="{Binding IdUtilizador}"/>
           </DataGrid.Columns>
       </DataGrid>

CaixaDetalhes

CaixasDetalhes查看

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="70"/>
            <RowDefinition Height="80"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="150"/>
            <RowDefinition Height="70"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0" Content="Posto:" VerticalAlignment="Top" HorizontalAlignment="Center" Style="{StaticResource lblEditarForms}" Margin="0,-5,0,0" />
            <ComboBox Grid.Column="0" x:Name="comboBoxPostos" VerticalAlignment="Bottom" HorizontalAlignment="Center" Width="300" Margin="0,0,0,5" Style="{DynamicResource ComboBoxProblemas}" ItemsSource="{Binding Postos}" SelectedItem="{Binding Detalhes.Posto}" SelectedValue="{Binding Detalhes.Posto.ID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="ID" DisplayMemberPath="Descricao"/>
            <Rectangle VerticalAlignment="Stretch" HorizontalAlignment="Right" Width="1" Stroke="#FF00256D" />
            <Label Grid.Column="1" Content="Exportado para o Olisoft?" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="35,0,0,0" Style="{StaticResource lblEditarForms}" FontSize="20"/>
            <CheckBox x:Name="cbExportado" Grid.Column="1" IsChecked="{Binding Detalhes.Exportado, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,20,0">
                <CheckBox.LayoutTransform>
                    <ScaleTransform ScaleX="1.5" ScaleY="1.5" />
                </CheckBox.LayoutTransform>
            </CheckBox>
            <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="1" Stroke="#FF00256D" Grid.ColumnSpan="2" />
        </Grid>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0" Content="Data do Caixa:" VerticalAlignment="Top" HorizontalAlignment="Center" Style="{StaticResource lblEditarForms}" FontSize="20"/>
            <DatePicker x:Name="dtPickerDataCaixa" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,15" FirstDayOfWeek="Monday" DisplayDateStart="2015-01-01" CalendarStyle="{StaticResource resizedCalendarItem}" SelectedDate="{Binding Detalhes.DataCaixa, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            <Rectangle VerticalAlignment="Stretch" HorizontalAlignment="Right" Width="1" Stroke="#FF00256D" />
            <Label Grid.Column="1" Content="Data Eliminado:" VerticalAlignment="Top" HorizontalAlignment="Center" Style="{StaticResource lblEditarForms}" FontSize="20"/>
            <DatePicker x:Name="dtPickerDataEliminado" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,15" FirstDayOfWeek="Monday" DisplayDateStart="2015-01-01" CalendarStyle="{StaticResource resizedCalendarItem}" SelectedDate="{Binding Detalhes.DataEliminado, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            <Rectangle Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Right" Width="1" Stroke="#FF00256D" />
            <Label Grid.Column="2" Content="Número do Caixa:" VerticalAlignment="Top" HorizontalAlignment="Center" Style="{StaticResource lblEditarForms}" FontSize="20"/>
            <TextBox x:Name="txtNumCaixa" Grid.Column="2" Height="28" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,15" Width="200"  MaxLines="1" FontSize="15" Text="{Binding Detalhes.NumCaixa, UpdateSourceTrigger=PropertyChanged}"/>
            <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="1" Stroke="#FF00256D" Grid.ColumnSpan="3" />
        </Grid>
        <Label Grid.Row="2" Content="Motivo" VerticalAlignment="Top" HorizontalAlignment="Center" Style="{StaticResource lblEditarForms}" FontSize="20" Margin="0,-6,0,0"/>
        <TextBox Grid.Row="2" x:Name="richTextBoxMotivo" Height="100" Width="655" FontFamily="Calibri" FontSize="18" VerticalAlignment="Bottom" BorderBrush="#AAAAAA" BorderThickness="1.5" Margin="0,0,0,8" Text="{Binding Detalhes.Motivo, UpdateSourceTrigger=PropertyChanged}"/>
        <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="1" Stroke="#FF00256D" Grid.Row="2" />
        <Label Grid.Row="3" Content="Observações" VerticalAlignment="Top" HorizontalAlignment="Center" Style="{StaticResource lblEditarForms}"  FontSize="20" Grid.RowSpan="2"/>
        <TextBox Grid.Row="3" x:Name="richTextBoxObservacoes" Height="100" Width="655" FontFamily="Calibri" FontSize="18" VerticalAlignment="Bottom" BorderBrush="#AAAAAA" BorderThickness="1.5" Margin="0,0,0,10" Text="{Binding Detalhes.Obs, UpdateSourceTrigger=PropertyChanged}" />
        <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="1" Stroke="#FF00256D" Grid.Row="3" />
        <UniformGrid Grid.Row="4" Columns="4" Height="70" Background="White" >
            <Button x:Name="btnGravar" Style="{StaticResource BotaoGridOperacoes}" CommandParameter="{Binding}" Command="{Binding Gravar}">
                <DockPanel LastChildFill="True" Width="115">
                    <Image Source="../../Imagens/save32black.png" Stretch="Fill" Width="32" Height="32" />
                    <TextBlock x:Name="txtBtnGravar" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FF00256D" Text="{Binding Path=AddSave, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"></TextBlock>
                </DockPanel>
            </Button>
            <Button Style="{StaticResource BotaoGridOperacoes}">
                <DockPanel LastChildFill="True" Width="115">
                    <Image Source="../../Imagens/new32Black.png" Stretch="Fill" Width="32" Height="32"   />
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FF00256D">Novo</TextBlock>
                </DockPanel>
            </Button>
            <Button Style="{StaticResource BotaoGridOperacoes}" >
                <DockPanel VerticalAlignment="Stretch" Width="125">
                    <Image Source="../../Imagens/bin2.png" Stretch="Fill" Width="32" Height="32"/>
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FF00256D">Eliminar</TextBlock>
                </DockPanel>
            </Button>
            <Button x:Name="btnSair" Style="{StaticResource BotaoGridOperacoes}" CommandParameter="{Binding}" Command="{Binding Sair}">
                <DockPanel VerticalAlignment="Stretch" Width="100">
                    <Image Source="/HelpDesk Assist;component/Avancado/Imagens/exit32.png" Stretch="Fill" Width="32" Height="32"  />
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FF00256D">Sair</TextBlock>
                </DockPanel>
            </Button>
        </UniformGrid>
    </Grid>

我的模型:

财报:

public class Caixa : BaseNotifyPropertyChanged
    {
        private int _id;
        private Posto _posto;
        private DateTime _dataCaixa;
        private DateTime _dataEliminado;
        private string _motivo;
        private int _numCaixa;
        private bool _exportado;
        private string _obs;
        private int _idUtilizador;

        public int Id
        {
            get => _id;
            set => SetField(ref _id, value);
        }

        public Posto Posto
        {
            get => _posto;
            set => SetField(ref _posto, value);
        }

        public DateTime DataCaixa
        {
            get => _dataCaixa;
            set => SetField(ref _dataCaixa, value);
        }

        public DateTime DataEliminado
        {
            get => _dataEliminado;
            set => SetField(ref _dataEliminado, value);
        }

        public string Motivo
        {
            get => _motivo;
            set => SetField(ref _motivo, value);
        }

        public int NumCaixa
        {
            get => _numCaixa;
            set => SetField(ref _numCaixa, value);
        }

        public bool Exportado
        {
            get => _exportado;
            set => SetField(ref _exportado, value);
        }

        public string Obs
        {
            get => _obs;
            set => SetField(ref _obs, value);
        }

        public int IdUtilizador
        {
            get => _idUtilizador;
            set => SetField(ref _idUtilizador, value);
        }
    } 

我的视图模型:

CaixasViewModel

public class CaixasViewModel : BaseNotifyPropertyChanged
    {
        public ObservableCollection<Caixa> Caixas { get; private set; }

        public CaixasViewModel()
        {
            int utilizadorAtual = Properties.Settings.Default.userID;
            Caixas = new ObservableCollection<Caixa>();
            Caixas = CaixaData.GetCaixasUtilizador(utilizadorAtual);
        }

        private Caixa _caixaSelecionado;
        public Caixa CaixaSelecionado
        {
            get { return _caixaSelecionado; }
            set
            {
                SetField(ref _caixaSelecionado, value);
                Delete.RaiseCanExecuteChanged();
                Edita.RaiseCanExecuteChanged();
            }
        }

        public DeleteCaixa Delete { get; private set; } = new DeleteCaixa();
        public EditaCaixa Edita { get; private set; } = new EditaCaixa();
        public NovoCaixa Novo { get; private set; } = new NovoCaixa();

        public class DeleteCaixa : BaseCommand
        {
            public override bool CanExecute(object parameter)
            {
                return parameter is CaixasViewModel viewModel && viewModel.CaixaSelecionado != null;
            }

            public override void Execute(object parameter)
            {
                CaixasViewModel viewModel = (CaixasViewModel)parameter;
                CaixaData.DeleteCaixa(viewModel.CaixaSelecionado.Id);
                _ = viewModel.Caixas.Remove(viewModel.CaixaSelecionado);
            }
        }

        public class NovoCaixa : BaseCommand
        {
            public override bool CanExecute(object parameter)
            {
                return parameter is CaixasViewModel;
            }

            public override void Execute(object parameter)
            {
                CaixasViewModel viewModel = (CaixasViewModel)parameter;
                Caixa caixa = new Caixa
                {
                    DataCaixa = DateTime.Now,
                    DataEliminado = DateTime.Now
                };
                CaixasDetalhesViewModel caixaDetalhes = new CaixasDetalhesViewModel(caixa);
                DetalhesCaixa dc = new DetalhesCaixa(caixaDetalhes)
                {
                    Owner = Application.Current.MainWindow
                };
                _ = dc.ShowDialog();
                if (dc.DialogResult.HasValue && dc.DialogResult.Value)
                {
                    viewModel.Caixas.Add(caixa);
                    viewModel.CaixaSelecionado = caixa;
                }
            }
        }

        public class EditaCaixa : BaseCommand
        {
            public override bool CanExecute(object parameter)
            {
                return parameter is CaixasViewModel viewModel && viewModel.CaixaSelecionado != null;
            }
            public override void Execute(object parameter)
            {
                CaixasViewModel viewModel = (CaixasViewModel)parameter;
                CaixasDetalhesViewModel caixaDetalhes = new CaixasDetalhesViewModel(viewModel.CaixaSelecionado);
                DetalhesCaixa detCaixa = new DetalhesCaixa(caixaDetalhes)
                {
                    Owner = Application.Current.MainWindow
                };
                _ = detCaixa.ShowDialog();
            }
        }
    }

CaixasDetalhesViewModel:

public class CaixasDetalhesViewModel : BaseNotifyPropertyChanged
    {
        public ObservableCollection<Posto> Postos { get; set; }

        public Caixa Detalhes { get; set; }

        public CaixasDetalhesViewModel(Caixa detalhes)
        {
            Postos = new ObservableCollection<Posto>();
            Postos = PostoData.GetPostosSimples();
            Detalhes = detalhes;
            EscolheFinal();
        }

        private string _addSave = "Inserir";
        public string AddSave
        {
            get => _addSave;
            set
            {
                _addSave = value;
                RaisePropertyChanged("AddSave");
            }
        }

        public void EscolheFinal()
        {
            AddSave = Detalhes.Id == 0 ? "Inserir" : "Gravar";
        }

        public Action DialogResult { get; set; }
        public Action CloseWindow { get; set; }

        public GravarCaixa Gravar { get; private set; } = new GravarCaixa();
        public SairCaixa Sair { get; private set; } = new SairCaixa();

        public class GravarCaixa : BaseCommand
        {
            public override bool CanExecute(object parameter)
            {
                return parameter is CaixasDetalhesViewModel viewModel;
            }

            public override void Execute(object parameter)
            {
                CaixasDetalhesViewModel viewModel = (CaixasDetalhesViewModel)parameter;
                viewModel.Detalhes.IdUtilizador = Properties.Settings.Default.userID;
                CaixaData.AdicionaCaixa(viewModel.Detalhes);
                viewModel.EscolheFinal();
                viewModel.DialogResult();

            }
        }

        public class SairCaixa : BaseCommand
        {
            public override bool CanExecute(object parameter)
            {
                return parameter is CaixasDetalhesViewModel viewModel;
            }
            public override void Execute(object parameter)
            {
                CaixasDetalhesViewModel viewModel = (CaixasDetalhesViewModel)parameter;
                viewModel.CloseWindow();

            }
        }

    }

全面的:

我可以使用 DialogResult 进行 CRUD,但我需要能够在 CaixaDetalhes 视图中插入/更新/删除“Caixa”而不关闭视图

编辑:如何在单击保存按钮时更新 Caixa Model? 我尝试使用“UpdateSourceTrigger=Explicit”,但尝试更改 Caixa 时没有任何反应。

我没有使用任何框架,如果可能的话,我想保持这种状态

我建议将保存命令的引用和当前修改的项目从CaixasViewModel传递给CaixasDetalhesViewModel 然后让CaixasViewModel修改它的Caixas集合,因为它是所有者。

您不应从视图 model 显示对话框。 从代码隐藏中显示它(参见下面的示例)。

下面的例子应该给你一个关于模式的原始概念:让主视图 model 创建并初始化对话框视图 model 并使用相应的保存命令和要修改的项目(添加和编辑)。 对话框视图 model 仅向用户公开要修改的项目,并执行从主视图 model 接收到的保存命令。 主视图 model 知道如何处理目标项目,例如,创建新实例(创建新对话框)或复制实例(编辑对话框)。

主要思想是创建要编辑的原始项目 model 的副本。 单击保存按钮时,通过将新数据复制回原始 model(编辑副本)来提交更改。

该示例还利用了可重用的RelayCommand ,通过降低代码复杂性来帮助提高可读性。 您可以在Microsoft Docs:Relaying Command Logic中找到原始实现。 只需将短代码复制到项目中名为RelayCommand的 class 并使用它,而不是为每个命令实现新的命令类。

CaixasViewModel.cs

class CaixasViewModel
{
  public ObservableCollection<Caixa> Caixas { get; private set; }

  public ICommand AddCaixaCommand => new RelayCommand(ExecuteAddCaixa);
  public ICommand ReplaceCaixaCommand 
    => new RelayCommand(ExecuteReplaceCaixa, commandParameter => this.CaixaSelecionado != null);
  public ICommand RemoveCaixaCommand => new RelayCommand(ExecuteRemoveCaixa);

  public CaixasDetalhesViewModel GetEditCaixaViewModel 
  { 
    var editSource = this.CaixaSelecionado.Clone();
    return new CaixasDetalhesViewModel(this.ReplaceCaixaCommand, editSource);
  }

  public CaixasDetalhesViewModel GetCreateCaixaViewModel 
  { 
    var editSource = new Caixa();
    return new CaixasDetalhesViewModel(this.AddCaixaCommand, editSource);
  }

  private void ExecuteAddCaixa(object commandParameter) 
    => this.Caixas.Add((Caixa)commandParameter);

  private void ExecuteReplaceCaixa(object commandParameter)
  {
    Caixa editedCaixa = (Caixa)commandParameter;
    var originalCaixa = this.Caixas.First(caixa => caixa.Id == editedCaixa.Id);
    
    // Copy data
    originalCaixa.Posto = editedCaixa.Posto;
    ...
  }

  private void ExecuteRemoveCaixa(object commandParameter) 
    => this.Caixas.Remove((Caixa)commandParameter);
}

CaixasDetalhesViewModel.cs

class  CaixasDetalhesViewModel : INotifyPropertyChanged
{
  public Caixa EditSource { get; set; }
  public ICommand SaveCommand { get; }

  public CaixasDetalhesViewModel(
    ICommand saveCommand, 
    Caixa editSource)
  {
    this.CommandProvider = saveCommand;
    this.EditSource = editSource;
  }
}

AssistenciasCaixas.xaml

<!-- DataContext is the CaixasViewModel -->
<Window>
  <StackPanel>
    <DataGrid x:Name="dgCaixas" />

    <Button Content="Open Edit Dialog" Click="OnEditDialogButtonClicked" />
    <Button Content="Open Create New Dialog" Click="OnCreateDialogButtonClicked" />
  </StackPanel>
</Window>

辅助Caixas.xaml.cs

partial class AssistenciasCaixas : Window
{
  private void OnEditDialogButtonClicked(object sender, EventArgs e)
  {    
    var viewModel = this.DataContex as CaixasViewModel;
    CaixasDetalhesViewModel caixaDetalhes = viewModel.GetEditCaixaViewModel();
    var dc = new DetalhesCaixa(caixaDetalhes);
    _ = dc.ShowDialog(); // Owner is automatically set on ShowDialog()

    // The following code is now handled in the CaixasViewModel
    //if (dc.DialogResult.HasValue && dc.DialogResult.Value)
    //{
    //  viewModel.Caixas.Add(caixa);
    //  viewModel.CaixaSelecionado = caixa;
    //}
  }

  private void OnCreateDialogButtonClicked(object sender, EventArgs e)
  {    
    var viewModel = this.DataContex as CaixasViewModel;
    CaixasDetalhesViewModel caixaDetalhes = viewModel.GetCreateCaixaViewModel();
    var dc = new DetalhesCaixa(caixaDetalhes);
    _ = dc.ShowDialog(); // Owner is automatically set on ShowDialog()

    // The following code is now handled in the CaixasViewModel
    //if (dc.DialogResult.HasValue && dc.DialogResult.Value)
    //{
    //  viewModel.Caixas.Add(caixa);
    //  viewModel.CaixaSelecionado = caixa;
    //}
  }
}

Caixa.cs

public class Caixa : ICloneable
{
  public int Id
  {
    get => _id;
    set => SetField(ref _id, value);
  }

  ...

  // Assumes that the property Posto is not editable via dialog,
  // otherwise clone Posto too (deep clone). 
  object ICloneable.Clone() => MemberwiseClone();
  public Caixa Clone() => ((ICloneable)this).Clone() as Caixa;
}

CaixaDetalhes.xaml

<!-- DataContext is the CaixasDetalhesViewModel -->
<Window>
  <StackPanel>
    <TextBox Text="{Binding EditSource.Motivo}" />
    <Button Content="Save" 
            Command="{Binding SaveCommand}"
            CommandParameter="{Binding EditSource}" />
  </StackPanel>
</Window>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM