На показанном рисунке, поскольку положительное значение 12V напрямую не связано с RaspberryPi, я думаю, что все должно быть хорошо. Однако вы можете повредить светодиодную полосу RGB, потому что большинство полос работают с 5V. Перед выполнением каких-либо подключений проверьте номинальную мощность полосы.
Следующее решение использует TextBox
для отображения пароля в виде обычного текста и PasswordBox
для маскировки пароля. PasswordBox
находится над TextBox
, поэтому сначала вы увидите замаскированный пароль. Когда флажок «показать пароль» установлен, PasswordBox
скрыт, что показывает TextBox
внизу (и пароль в виде обычного текста). Вот XAML:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="VisibilityConverter" />
</Window.Resources>
<StackPanel>
<Grid>
<TextBox
Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}"
/>
<PasswordBox
x:Name="PasswordBox"
PasswordChanged="OnPasswordChanged"
Visibility="{Binding HidePassword, Converter={StaticResource VisibilityConverter}}"
/>
</Grid>
<CheckBox
Content="Show password"
IsChecked="{Binding ShowPassword}"
/>
</StackPanel>
Он не использует MVVM для всего (обратите внимание на обработчик событий OnPasswordChanged
). Это потому, что PasswordBox
не может использовать привязку, поэтому пароль должен быть установлен в коде позади. Но прежде чем показать это, вот модель представления:
public class ViewModel : ViewModelBase
{
private string _password;
public string Password
{
get => _password;
set => Set(ref _password, value);
}
private bool _showPassword;
public bool ShowPassword
{
get => _showPassword;
set
{
Set(ref _showPassword, value);
RaisePropertyChanged(nameof(HidePassword));
}
}
public bool HidePassword => !ShowPassword;
}
Методы Set
происходят из родительского класса ViewModelBase
, который является частью легкого инструментария MVVM. Метод Set
просто устанавливает поле поддержки свойства и вызывает событие PropertyChanged
для этого свойства.
Наконец, вот код:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InitializeViewModel();
}
public ViewModel ViewModel => DataContext as ViewModel;
private void InitializeViewModel()
{
DataContext = new ViewModel();
ViewModel.PropertyChanged += (sender, args) =>
{
// Update the password box only when it's not visible;
// otherwise, the cursor goes to the beginning on each keystroke
if (!PasswordBox.IsVisible)
{
if (args.PropertyName == nameof(ViewModel.Password))
PasswordBox.Password = ViewModel.Password;
}
};
}
private void OnPasswordChanged(object sender, RoutedEventArgs e)
{
ViewModel.Password = PasswordBox.Password;
}
}
После установки для DataContext
нового ViewModel
, мы слушаем изменения в свойстве Password
, чтобы обновить его в [ 1118]. Обратите внимание, что мы делаем это только тогда, когда PasswordBox
не виден (в противном случае курсор устанавливается на начало при каждом нажатии клавиши, и мы в конечном итоге возвращаем пароль!)
Обработчик событий просто обновляет [ 1120] в модели представления всякий раз, когда она изменяется в PasswordBox
.
Код для «подтверждения пароля» TextBox
и PasswordBox
будет очень похожим.
Вы можете решить эту проблему с помощью конвертера, который проверяет, следует ли вам скрывать или показывать фактический текст.
Используя MultiValueConverter, мы можем передать как исходный текст, так и bool, который указывает, следует ли нам его скрывать или показывать. Тогда возвращаемое значение является либо фактическим текстом, либо скрытым: :
<Window.Resources>
<local:PasswordToHiddenCharactersConverter x:Key="PasswordToHiddenCharactersConverter" />
</Window.Resources>
<StackPanel>
<CheckBox x:Name="HidePasswordBox" Content="Hide Password" />
<TextBox >
<TextBox.Text>
<MultiBinding Converter="{StaticResource PasswordToHiddenCharactersConverter}" UpdateSourceTrigger="PropertyChanged">
<Binding Path="Password" />
<Binding ElementName="HidePasswordBox" Path="IsChecked" />
</MultiBinding>
</TextBox.Text>
</TextBox>
</StackPanel>
«Пароль» - это имя свойства в нашей ViewModel, для CheckBox мы можем напрямую связать его изнутри xaml без необходимости проходить через ViewModel