#c# #wpf #mvvm #icommand
#c# #wpf #mvvm #icommand
Вопрос:
Я новичок в разработке WPF, и я также не продвинулся дальше с Google. Я не понимаю, как я могу проверить свои данные модели с помощью ICommand
. Я понимаю, что есть аннотации и что ICommand
интерфейс предлагает canExecute
метод. Например, я хочу сказать, что имя и фамилия обязательны. Я пробовал это с [Required(ErrorMessage = "Title is required.")]
в моем классе модели, но у меня не получается. может кто-нибудь мне помочь.
Пока у меня есть следующее:
public class Student : INotifyPropertyChanged
{
private string name;
private string surname;
private int age;
private string course;
public string Course
{
get { return course; }
set
{
course = value;
OnPropertyChanged();
}
}
public int Age
{
get { return age; }
set
{
age = value;
OnPropertyChanged();
}
}
public string Surname
{
get { return surname; }
set
{
surname = value;
OnPropertyChanged();
}
}
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class StudentViewModel
{
private IList<Student> _studentList;
public StudentViewModel()
{
_studentList = new List<Student>
{
new Student{Name="Todd",Surname="Johnsen",Age=29,Course="Software-Development"},
new Student{Name="Mike",Surname="Kroshka",Age=31,Course="Marketing"},
new Student{Name="Marie",Surname="Tedd",Age=21,Course="Marketing"},
new Student{Name="Susane",Surname="Müller",Age=31,Course="Marketing"},
new Student{Name="Herbert",Surname="Rehl",Age=18,Course="Software-Development"},
new Student{Name="Markus",Surname="Stanz",Age=23,Course="Software-Development"},
new Student{Name="Sabine",Surname="Bergsen",Age=19,Course="Marketing"}
};
}
public IList<Student> Students
{
get { return _studentList; }
set { _studentList = value; }
}
private ICommand mUpdater;
public ICommand UpdateCommand
{
get
{
if(mUpdater == null)
{
mUpdater = new Updater();
}
return mUpdater;
}
set
{
mUpdater = value;
}
}
}
public class Updater : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
}
}
<Window x:Class="Student_list_mvvm_wpf_core.MainWindowView"
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:Student_list_mvvm_wpf_core"
mc:Ignorable="d"
Title="Student-list" Height="350" Width="600">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0">Name</Label>
<Label Grid.Row="1">Surname</Label>
<Label Grid.Row="2">Age</Label>
<Label Grid.Row="3">Course</Label>
<Button x:Name="btnUpdateStudent" Grid.Row="3" Grid.Column="2"
Width="100" Margin="2" HorizontalAlignment="Left"
Command="{Binding Path=UpdateCommand}">Update Student</Button>
<ListView x:Name="studentGrid" ItemsSource="{Binding Students}"
Grid.Row="4" Grid.ColumnSpan="3" Margin="5">
<ListView.View>
<GridView x:Name="gridStudent">
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="100" />
<GridViewColumn Header="Surname" DisplayMemberBinding="{Binding Surname}" Width="100" />
<GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}" Width="50" />
<GridViewColumn Header="Course" DisplayMemberBinding="{Binding Course}" Width="200" />
</GridView>
</ListView.View>
</ListView>
<TextBox Grid.Row="0" Grid.Column="1" Width="200"
HorizontalAlignment="Left" Margin="2"
Text="{Binding SelectedItem.Name, ElementName=studentGrid}"
x:Name="txtName"></TextBox>
<TextBox Grid.Row="1" Grid.Column="1" Width="200"
HorizontalAlignment="Left" Margin="2"
Text="{Binding SelectedItem.Surname, ElementName=studentGrid}"
x:Name="txtSurname"></TextBox>
<TextBox Grid.Row="2" Grid.Column="1" Width="200"
HorizontalAlignment="Left" Margin="2"
Text="{Binding SelectedItem.Age, ElementName=studentGrid}"
x:Name="txtAge"></TextBox>
<TextBox Grid.Row="3" Grid.Column="1" Width="200"
HorizontalAlignment="Left" Margin="2"
Text="{Binding SelectedItem.Course, ElementName=studentGrid}"
x:Name="txtCourse"></TextBox>
</Grid>
Ответ №1:
Использование IDataErrorInfo
для проверки вашей модели выглядит более подходящим в вашем случае. Сначала обновите свой ViewModel
, чтобы иметь свойство, связанное с ListView
‘s SelectedItem
:
public Student SelectedStudent
{
get { return _selectedStudent; }
set { _selectedStudent = value; }
}
Во-вторых, обновите Student
модель для проверки данных:
public class Student : INotifyPropertyChanged, IDataErrorInfo
{
private string name;
private string surname;
private int age;
private string course;
public string Course
{
get { return course; }
set
{
course = value;
OnPropertyChanged();
}
}
public int Age
{
get { return age; }
set
{
age = value;
OnPropertyChanged();
}
}
public string Surname
{
get { return surname; }
set
{
surname = value;
OnPropertyChanged();
}
}
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged();
}
}
public string Error => string.Empty;
public string this[string columnName]
{
get
{
string result = null;
if (columnName == "Name")
{
if (string.IsNullOrEmpty(Name))
result = "Name is required.";
}
if (columnName == "Surname")
{
if (string.IsNullOrEmpty(Surname))
result = "Surname is required.";
}
return resu<
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Наконец, обновите свой xaml:
-Привязка между вашим ListView's
SelectedItem
и созданным вами Свойством.
-Проверка TextBox's
текста
<TextBox Grid.Row="0" Grid.Column="1" Width="200"
HorizontalAlignment="Left" Margin="2"
Text="{Binding SelectedStudent.Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true, NotifyOnValidationError=False}"
x:Name="txtName"></TextBox>
<TextBox Grid.Row="1" Grid.Column="1" Width="200"
HorizontalAlignment="Left" Margin="2"
Text="{Binding SelectedStudent.Surname,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true, NotifyOnValidationError=False}"
x:Name="txtSurname"></TextBox>
-Добавьте MultiDataTrigger
для включения и отключения Button
при выполнении подходящих условий.
<Button x:Name="btnUpdateStudent" Grid.Row="3" Grid.Column="2"
Width="100" Margin="2" HorizontalAlignment="Left"
Content="Update Student" Command="{Binding UpdateCommand}">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=txtName, Path=(Validation.HasError)}" Value="false" />
<Condition Binding="{Binding ElementName=txtSurname, Path=(Validation.HasError)}" Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Вывод:
Вот суть для полного исходного кода. Если вы настаиваете на использовании canExecute
, это должно помочь.
Комментарии:
1. Спасибо за ваши усилия!!
2. @TheWorldDrown добро пожаловать, пожалуйста, примите ответ, если он был полезен 🙂