Можно ли передать экземпляр класса в параметр команды?
Можно ли передать экземпляр класса в параметр команды?
ViewModel
public class RegLeftViewModel : ViewModelBase
{
public EmailContainer RegEmailContainer { get; } = new EmailContainer() { Email = "", Code = 0 };
Random random = new Random();
private int code;
private string regEmailEntered = "";
public string RegEmailEntered
{
get => regEmailEntered;
set => Set(ref regEmailEntered, value);
}
private string regLoginEntered;
public string RegLoginEntered
{
get => regLoginEntered;
set {
code = random.Next(1000, 9999);
RegEmailContainer.Code = code;
Set(ref regLoginEntered, value);
RegEmailContainer.Email = value;
}
}
private string regPasswordEntered;
public RegLeftViewModel()
{
SendEmailCommand = new SendEmailCommand();
RegCommand = new LambdaCommand(OnRegCommandExecuted, CanRegCommandExecute);
}
public string RegPasswordEntered
{
get => regPasswordEntered;
set => Set(ref regPasswordEntered, value);
}
private bool IfPasswordRight = false;
private bool IfCodeRight { get; set; }
public ICommand SendEmailCommand { get; }
public ICommand RegCommand { get; }
public void OnRegCommandExecuted(object p)
{
DB.Reg(RegLoginEntered, RegPasswordEntered, RegEmailEntered);
}
public bool CanRegCommandExecute(object p) => !DB.IfLoginCreated(RegLoginEntered) && IfPasswordRight && IfCodeRight;
}
XAML
<UserControl x:Class="FinalWPFApp.Views.LogReg.RegLeftView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FinalWPFApp.Views.LogReg"
mc:Ignorable="d"
Width="522" Height="500" Background="Transparent"
FontWeight="Light">
<Grid>
<Border
BorderThickness="2"
CornerRadius="40"
Margin="50, 55, 25, 55"
>
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBB8B8B"/>
<GradientStop Color="#FFB67272" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<StackPanel Orientation="Vertical" Margin="20,25,20,25">
<Grid >
<TextBox Name="EmailTextBox" Style="{StaticResource LoginTextBoxStyle}" Text="{Binding RegEmailEntered, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="Почта" Tag="{Binding ElementName=EmailTextBox}"
Style="{StaticResource PlaceholderStyle}" />
</Grid>
<Border BorderThickness="0.5">
<Border.BorderBrush>
<SolidColorBrush Color="#FF367E40" Opacity="0.8"/>
</Border.BorderBrush>
</Border>
<DockPanel HorizontalAlignment="Center" Margin="0, 30, 0, 0" VerticalAlignment="Center">
<StackPanel Orientation="Vertical">
<Grid >
<TextBox MaxLength="4" Width="82" Name="NumberTextBox" Style="{StaticResource LoginTextBoxStyle}" />
<TextBlock Text="Код" Tag="{Binding ElementName=NumberTextBox}"
Style="{StaticResource PlaceholderStyle}"/>
</Grid>
<Border BorderThickness="0.5">
<Border.BorderBrush>
<SolidColorBrush Color="#FF367E40" Opacity="0.8"/>
</Border.BorderBrush>
</Border>
</StackPanel>
<Button Margin="80, 3, 0, 3" Content="Подтвердить" FontSize="20" Style="{StaticResource ButtonMouseRLStyle}" Width="130" Cursor="Hand" Command="{Binding SendEmailCommand}" CommandParameter="{Binding RegEmailContainer, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
<Grid Margin="0,30,0,0">
<TextBox Name="LoginTextBox" Style="{StaticResource LoginTextBoxStyle}" />
<TextBlock Text="Логин" Tag="{Binding ElementName=LoginTextBox}"
Style="{StaticResource PlaceholderStyle}"/>
</Grid>
<Border BorderThickness="0.5">
<Border.BorderBrush>
<SolidColorBrush Color="#FF367E40" Opacity="0.8"/>
</Border.BorderBrush>
</Border>
<Grid Margin="0,30,0,0">
<TextBox Name="PasswordTextBox" Style="{StaticResource LoginTextBoxStyle}" />
<TextBlock Text="Пароль" Tag="{Binding ElementName=PasswordTextBox}"
Style="{StaticResource PlaceholderStyle}"/>
</Grid>
<Border BorderThickness="0.5">
<Border.BorderBrush>
<SolidColorBrush Color="#FF367E40" Opacity="0.8"/>
</Border.BorderBrush>
</Border>
<Button Margin="50, 30, 50, 0" Content="Зарегистрироваться" FontSize="20" Style="{StaticResource ButtonMouseRLStyle}" Cursor="Hand" Height="35">
</Button>
</StackPanel>
</Border>
</Grid>
</UserControl>
Сама команда
public class SendEmailCommand : CommandBase
{
public override bool CanExecute(object parameter)
{
if (parameter.ToString() == "1")
{
return false;
}
return true;
}
public override void Execute(object parameter)
{
EmailContainer emailContainer = (EmailContainer)parameter;
EmailServices.SendCode(emailContainer.Email, emailContainer.Code);
}
}
Выдает исключение, что парамент равен null. Это проблема в коде или так в принципе нельзя делать?
Ответы (1 шт):
Не занимайтесь переопределением поведения команды, используйте LambdaCommand. Так как я не вижу вашей реализации LambdaCommand, я вам покажу свою.
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
=> (_execute, _canExecute) = (execute, canExecute);
public bool CanExecute(object parameter)
=> _canExecute == null || _canExecute(parameter);
public void Execute(object parameter)
=> _execute(parameter);
}
Далее получается вот такой конструктор
public RegLeftViewModel()
{
SendEmailCommand = new RelayCommand(parameter =>
{
EmailContainer emailContainer = (EmailContainer)parameter;
EmailServices.SendCode(emailContainer.Email, emailContainer.Code);
}, parameter => parameter is EmailContainer); // не совсем понятно, что вы здесь хотели проверить
RegCommand = new RelayCommand(parameter =>
{
DB.Reg(RegLoginEntered, RegPasswordEntered, RegEmailEntered);
}, parameter => !DB.IfLoginCreated(RegLoginEntered));
}
Подозреваю, что ваша LambdaCommand делает то же самое. Вот и всё лямбдами решается очень просто без добавления лишних методов и классов.
Еще вот это CommandParameter="{Binding RegEmailContainer, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" должно выглядеть так CommandParameter="{Binding RegEmailContainer}", откуда вы вообще взяли, что UpdateSourceTrigger здесь имеет какой-либо смысл? Привязка к get-only свойству, а вы описываете правила его перезаписи.