У меня есть программа, которая до сих пор следует принципам / правилам MVVM с кодом 0 позади, и у меня есть DataGrid, где пользователи могут добавлять, редактировать или удалять строки, которые представляют студентов. Пользователь может добавить строку в список, нажав кнопку «+», но для редактирования строки пользователь должен сначала щелкнуть по только что добавленной строке, которая не так удобна для пользователя.
Я давно пытался установить новую добавленную строку в EditMode, но все мои попытки либо потерпели неудачу, либо сработали, но с некоторыми побочными эффектами для остальной части программы. Я посмотрел его в Интернете, и решения, которые я нашел, выглядят как излишние или имеют плохой побочный эффект.
Я создал аналогичную программу с меньшим количеством кода, чтобы упростить показ структуры моей программы и DataGrid:
Модель
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public string PhoneNumber { get; set; }
public string Address { get; set; }
public string Email { get; set; }
}
ViewModel
public class StudentsViewModel : INotifyPropertyChanged
{
public StudentsViewModel()
{
Students = new ObservableCollection<Student>();
}
private ObservableCollection<Student> students;
public ObservableCollection<Student> Students
{
get { return students; }
set
{
students = value;
NotifyPropertyChanged(nameof(Students));
}
}
private Student selectedStudent;
public Student SelectedStudent
{
get { return selectedStudent; }
set
{
selectedStudent = value;
NotifyPropertyChanged(nameof(SelectedStudent));
}
}
private ICommand addRow;
public ICommand AddRow
{
get
{
if(addRow == null)
{
addRow = new RelayCommand(
parameter => AddStudent(new Student()),
parameter => true
);
}
return addRow;
}
}
private ICommand removeCmd;
public ICommand RemoveCmd
{
get
{
removeCmd = new RelayCommand(
parameter => RemoveStudent(parameter as Student),
parameter => parameter != null
);
return removeCmd;
}
}
private void AddStudent(Student studentToAdd)
{
Students.Add(studentToAdd);
}
private void RemoveStudent(Student studentToRemove)
{
if (Students.Contains(studentToRemove))
{
Students.Remove(studentToRemove);
}
}
#region INotify
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
View
<Window x:Class="DataGridExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataGridExample"
mc:Ignorable="d"
Title="MainWindow"
Height="600"
Width="1000">
<Window.Resources>
<local:StudentsViewModel x:Key="StudentsVm"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource StudentsVm}}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<DockPanel LastChildFill="False"
Background="#FF2C58EC">
<Button Command="{Binding AddRow}"
Height="25"
Margin="5">
<Button.Template>
<ControlTemplate>
<Image Source="/Images/AddItem.png"/>
</ControlTemplate>
</Button.Template>
</Button>
<Button Command="{Binding RemoveCmd}"
CommandParameter="{Binding ElementName=StudentDataGrid, Path=SelectedItem}"
Height="25"
Margin="5">
<Button.Template>
<ControlTemplate>
<Image Source="/Images/DeleteItem.png"/>
</ControlTemplate>
</Button.Template>
</Button>
</DockPanel>
<DataGrid ItemsSource="{Binding Students}"
SelectedItem="{Binding Source={StaticResource StudentsVm}, Path=SelectedStudent, Mode=TwoWay}"
x:Name="StudentDataGrid"
ColumnWidth="*"
CanUserAddRows="False"
CanUserResizeRows="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
CanUserDeleteRows="False"
AutoGenerateColumns="False"
Grid.Row="1">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding FirstName, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Header="First Name">
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding LastName, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Header="Last Name">
</DataGridTextColumn>
<DataGridTemplateColumn Header="Date of Birth">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding DateOfBirth, StringFormat={}{0:dd.MM.yyyy}, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding DateOfBirth, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
DisplayDate="{Binding DateOfBirth, Mode=OneWay, UpdateSourceTrigger=LostFocus}">
</DatePicker>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding PhoneNumber, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Header="Phone Number">
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Address, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Header="Address">
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Email, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Header="Email">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Я бы предпочел, чтобы решение было совместимым с MVVM, но честно на данном этапеЯ был бы удовлетворен, пока это не вызывает других проблем и не требует тонны фреймворков или нескольких файлов, полных кода.
Я бы предпочел, чтобы результат выглядел как этот пример но это также допустимо , если после нажатия кнопки «+» не происходит движения мыши.