[英]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
<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.