WPF 的现代 UI - ModernDialog:仅在某些情况下允许单击“确定”
Modern UI for WPF - ModernDialog: Allow to click Ok only on some conditions
我开始了一个新的小项目,使用 ModernUI for WPF。
我要显示一个只有两个文本框和两个按钮的对话框 (ok/cancel)。
两个文本框有一些验证(一个是名字应该>0,另一个应该是电子邮件)。
目前我有以下内容:
var userEditionForm = new UserEditionForm(oneUserConfigurationViewModel);
var dlg = new ModernDialog
{
Title = "User edition",
Content = userEditionForm,
Width = 300
};
dlg.Buttons = new[] {dlg.OkButton, dlg.CancelButton};
dlg.ShowDialog();
return dlg.DialogResult.HasValue && dlg.DialogResult.Value;
内容用户控件是:
<UserControl x:Class="Test.UserControls.UserEditionForm"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<Style TargetType="StackPanel">
<Setter Property="Orientation" Value="Horizontal" />
<Setter Property="Margin" Value="0,0,0,4" />
</Style>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="Width" Value="100" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</StackPanel.Resources>
<StackPanel>
<Label Content="Name" Target="{Binding ElementName=TextFirstName}" />
<TextBox x:Name="TextFirstName" Width="150"
Text="{Binding User.Name, RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</StackPanel>
<StackPanel>
<Label Content="Email" Target="{Binding ElementName=TextEmail}" />
<TextBox x:Name="TextEmail" Width="150"
Text="{Binding User.Email, RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
验证已完成,但我想阻止用户单击 "OK",直到验证成功。可能吗?如果是,如何?
这实际上很棘手,但对我有用:
ViewModel
public class UserInfo : INotifyPropertyChanged, IDataErrorInfo
{
private static Regex emailRegex = new Regex(@"^\w+(?:\.\w+)*?@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$");
private string firstname;
private string email;
public string FirstName
{
get { return firstname; }
set { firstname = value; OnPropertyChanged(); }
}
public string EMail
{
get { return email; }
set { email = value; OnPropertyChanged(); }
}
public string Error
{
get { return null; }
}
public string this[string columnName]
{
get
{
switch (columnName)
{
case "FirstName":
return string.IsNullOrWhiteSpace(FirstName) ? "Firstname is required!" : null;
case "EMail":
return EMail == null || !emailRegex.IsMatch(EMail) ? "The Email Address is not valid!" : null;
default:
return null;
}
}
}
public LoginCommand LoginCommand { get; private set; }
public UserInfo()
{
LoginCommand = new LoginCommand(this);
}
private void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
命令(不知道你想叫它什么...)
public class LoginCommand : ICommand
{
private UserInfo info;
private ICommand attachedCommand;
public bool CanExecute(object parameter)
{
return parameter != null && info["FirstName"] == null && info["EMail"] == null;
}
public event EventHandler CanExecuteChanged = delegate { };
public void Execute(object parameter)
{
Debug.WriteLine("This Works!");
//Add execution logic here
if (attachedCommand != null)
{
attachedCommand.Execute(parameter); //should close the window
}
}
private void Info_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
CanExecuteChanged(this, new EventArgs());
}
public LoginCommand(UserInfo info)
{
this.info = info;
info.PropertyChanged += Info_PropertyChanged;
}
public void AttachCommand(ICommand command) //attach the original command here
{
attachedCommand = command;
}
}
ModernUI 的用法
UserInfo info = new UserInfo();
UserInfoForm form = new UserInfoForm(info);
ModernDialog dialog = new ModernDialog
{
Title = "User edition",
Content = form,
Width = 300
};
Button btnOk = dialog.OkButton;
ICommand originalCommand = btnOk.Command; //the original command should close the window so i keep it
btnOk.Command = info.LoginCommand;
info.LoginCommand.AttachCommand(originalCommand); //and attach it to my command
dialog.Buttons = new[] { btnOk, dialog.CancelButton };
dialog.ShowDialog();
我开始了一个新的小项目,使用 ModernUI for WPF。
我要显示一个只有两个文本框和两个按钮的对话框 (ok/cancel)。
两个文本框有一些验证(一个是名字应该>0,另一个应该是电子邮件)。
目前我有以下内容:
var userEditionForm = new UserEditionForm(oneUserConfigurationViewModel);
var dlg = new ModernDialog
{
Title = "User edition",
Content = userEditionForm,
Width = 300
};
dlg.Buttons = new[] {dlg.OkButton, dlg.CancelButton};
dlg.ShowDialog();
return dlg.DialogResult.HasValue && dlg.DialogResult.Value;
内容用户控件是:
<UserControl x:Class="Test.UserControls.UserEditionForm"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<Style TargetType="StackPanel">
<Setter Property="Orientation" Value="Horizontal" />
<Setter Property="Margin" Value="0,0,0,4" />
</Style>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="Width" Value="100" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</StackPanel.Resources>
<StackPanel>
<Label Content="Name" Target="{Binding ElementName=TextFirstName}" />
<TextBox x:Name="TextFirstName" Width="150"
Text="{Binding User.Name, RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</StackPanel>
<StackPanel>
<Label Content="Email" Target="{Binding ElementName=TextEmail}" />
<TextBox x:Name="TextEmail" Width="150"
Text="{Binding User.Email, RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
验证已完成,但我想阻止用户单击 "OK",直到验证成功。可能吗?如果是,如何?
这实际上很棘手,但对我有用:
ViewModel
public class UserInfo : INotifyPropertyChanged, IDataErrorInfo
{
private static Regex emailRegex = new Regex(@"^\w+(?:\.\w+)*?@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$");
private string firstname;
private string email;
public string FirstName
{
get { return firstname; }
set { firstname = value; OnPropertyChanged(); }
}
public string EMail
{
get { return email; }
set { email = value; OnPropertyChanged(); }
}
public string Error
{
get { return null; }
}
public string this[string columnName]
{
get
{
switch (columnName)
{
case "FirstName":
return string.IsNullOrWhiteSpace(FirstName) ? "Firstname is required!" : null;
case "EMail":
return EMail == null || !emailRegex.IsMatch(EMail) ? "The Email Address is not valid!" : null;
default:
return null;
}
}
}
public LoginCommand LoginCommand { get; private set; }
public UserInfo()
{
LoginCommand = new LoginCommand(this);
}
private void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
命令(不知道你想叫它什么...)
public class LoginCommand : ICommand
{
private UserInfo info;
private ICommand attachedCommand;
public bool CanExecute(object parameter)
{
return parameter != null && info["FirstName"] == null && info["EMail"] == null;
}
public event EventHandler CanExecuteChanged = delegate { };
public void Execute(object parameter)
{
Debug.WriteLine("This Works!");
//Add execution logic here
if (attachedCommand != null)
{
attachedCommand.Execute(parameter); //should close the window
}
}
private void Info_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
CanExecuteChanged(this, new EventArgs());
}
public LoginCommand(UserInfo info)
{
this.info = info;
info.PropertyChanged += Info_PropertyChanged;
}
public void AttachCommand(ICommand command) //attach the original command here
{
attachedCommand = command;
}
}
ModernUI 的用法
UserInfo info = new UserInfo();
UserInfoForm form = new UserInfoForm(info);
ModernDialog dialog = new ModernDialog
{
Title = "User edition",
Content = form,
Width = 300
};
Button btnOk = dialog.OkButton;
ICommand originalCommand = btnOk.Command; //the original command should close the window so i keep it
btnOk.Command = info.LoginCommand;
info.LoginCommand.AttachCommand(originalCommand); //and attach it to my command
dialog.Buttons = new[] { btnOk, dialog.CancelButton };
dialog.ShowDialog();