Как сделать Custom Control как PasswordBox где слева от passwordboxa будет textblock(значок замка или другой символ). Тоесть объеденить passwordbox и textblock в 1 control. У которого я смогу получать значения Password.
Была идея сделать у PasswordBoxa ControlTemplate из textblock
a и passwordbox`a
Но мне также нужно чтоб в MainWindow.xaml я мог изменять стиль
cs:CustomPassBox Style={StaticResource DefaultStyle}>
Но когда я так определяю стиль у контрола то controlTemplate исчезает.
Ну смотрите, основная цель, это сделать два элемента внутри одного и добавить возможность использовать стили. Можно пойти несколькими путями.
Использование стилей:
Тут смысл в чем, мы делаем некий базовый стиль, в котором переопределяем то, что нам нужно и добавляем новое.
К примеру имеем такой стиль для PasswordBox
:
<Style x:Key="MainStyle" TargetType="PasswordBox">
<Setter Property="Height" Value="30"/>
<Setter Property="Width" Value="150"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Viewbox>
<Canvas Width="24" Height="24">
<Path Data="M12,17C10.89,17 10,16.1 10,15C10,13.89 10.89,13 12,13A2,2 0 0,1 14,15A2,2 0 0,1 12,17M18,20V10H6V20H18M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10C4,8.89 4.89,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z" Fill="Black" />
</Canvas>
</Viewbox>
<Border Grid.Column="1" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Center" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
При применении его мы получим следующий результат:
<PasswordBox Style="{StaticResource MainStyle}" Password="1234" />
Теперь мы допустим хотим задать какой нибудь стиль к примеру для ошибок, тогда создаем другой стиль и задаем ему BaseOn
, что унаследует все от базового стиля:
<Style x:Key="ErrorStyle" TargetType="PasswordBox" BasedOn="{StaticResource MainStyle}">
<Setter Property="Background" Value="#99DE0000"/>
<Setter Property="Foreground" Value="White"/>
</Style>
Применяем и смотрим результат:
<PasswordBox Style="{StaticResource ErrorStyle}" Password="1234" />
Использование UserControl:
Тут все примерно тоже самое, но только есть еще такая вещь, как DependencyProperty
. С ее помощью мы можем передавать в наш Control не стандартные свойства (как примеру у PasswordBox
есть свойство Password
, мы можем сделать тоже самое но допустим для переопределения иконки), UserControl также поддерживает стили. Давайте создадим что то простенькое:
Добавим UserControl с таким стилем:
<UserControl x:Class="WpfApp1.CustomPasswordBox"
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:WpfApp1"
mc:Ignorable="d"
x:Name="uc"
Height="30" Width="150">
<UserControl.Resources>
<StreamGeometry x:Key="DefaultData">
M12,17C10.89,17 10,16.1 10,15C10,13.89 10.89,13 12,13A2,2 0 0,1 14,15A2,2 0 0,1 12,17M18,20V10H6V20H18M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10C4,8.89 4.89,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z
</StreamGeometry>
</UserControl.Resources>
<UserControl.Template>
<ControlTemplate TargetType="UserControl">
<ContentPresenter/>
</ControlTemplate>
</UserControl.Template>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Viewbox>
<Canvas Width="24" Height="24">
<Path Data="{Binding ElementName=uc, Path=Icon, FallbackValue={StaticResource DefaultData}, TargetNullValue={StaticResource DefaultData}}" Fill="Black" />
</Canvas>
</Viewbox>
<PasswordBox x:Name="PBox" Grid.Column="1" Foreground="{Binding ElementName=uc, Path=Foreground}" Background="{Binding ElementName=uc, Path=Background}" VerticalContentAlignment="Center" />
</Grid>
</UserControl>
И определим пару DP:
public partial class CustomPasswordBox : UserControl
{
public CustomPasswordBox()
{
InitializeComponent();
PBox.PasswordChanged += (sender, args) => {
Password = ((PasswordBox) sender).SecurePassword;
};
}
public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register(
"Password", typeof(SecureString), typeof(CustomPasswordBox), new PropertyMetadata(default(SecureString)));
public SecureString Password
{
get => (SecureString)GetValue(PasswordProperty);
set => SetValue(PasswordProperty, value);
}
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
"Icon", typeof(StreamGeometry), typeof(CustomPasswordBox), new PropertyMetadata(default(StreamGeometry)));
public StreamGeometry Icon
{
get => (StreamGeometry) GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
}
Тут я для примера задал два DependencyProperty:
PasswordChanged
событие. В интернете много примеров как это обойти, будет интересно, думаю найдете...Теперь давайте вызовем это и посмотрим на результат:
<local:CustomPasswordBox />
Создадим стиль под наш новый UserControl, переопределим цвета и иконку:
<StreamGeometry x:Key="KeyIcon">
M21,11C21,16.55 17.16,21.74 12,23C6.84,21.74 3,16.55 3,11V5L12,1L21,5V11M12,21C15.75,20 19,15.54 19,11.22V6.3L12,3.18L5,6.3V11.22C5,15.54 8.25,20 12,21M12,6A3,3 0 0,1 15,9C15,10.31 14.17,11.42 13,11.83V14H15V16H13V18H11V11.83C9.83,11.42 9,10.31 9,9A3,3 0 0,1 12,6M12,8A1,1 0 0,0 11,9A1,1 0 0,0 12,10A1,1 0 0,0 13,9A1,1 0 0,0 12,8Z
</StreamGeometry>
<Style x:Key="ErrorStyle" TargetType="local:CustomPasswordBox">
<Setter Property="Background" Value="#99DE0000"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Icon" Value="{StaticResource KeyIcon}"/>
</Style>
Результат:
<local:CustomPasswordBox Style="{StaticResource ErrorStyle}" />
Собственно вот так довольно просто мы можем работать с элементами.
Удачи в изучении WPF!
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Вопрос 1: Через парсер получаем строку "10д 5ч"(10 дней и 5 часов) Надо ее конвертировать и получить время в часах (10*24+5) и получить число 245
Я хочу сделать, чтоб при вводе данных в C# не выполнялся переход на новую строку в консоли, это возможно? Например, чтоб консоль выглядела не так:
Как программно в dataGridView сделать поле ComboBox?
пишу приложение WPF с веб сервисом wfc, в веб сервесе модель базы данных entity framework, когда пытаюсь передать запрос из клиента на добавление записи...