Комментарии 20
Мы для похожих проблем используем Behavior-ы.
0
Поддерживаю. Оставлю свою реализацию для наглядности:
И использование:
public class PasswordBehavior : Behavior<PasswordBox>
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(string), typeof(PasswordBehavior), new PropertyMetadata(default(string)));
private bool _skipUpdate;
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.PasswordChanged += PasswordBox_PasswordChanged;
}
protected override void OnDetaching()
{
AssociatedObject.PasswordChanged -= PasswordBox_PasswordChanged;
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == PasswordProperty)
{
if (!_skipUpdate)
{
_skipUpdate = true;
AssociatedObject.Password = e.NewValue as string;
_skipUpdate = false;
}
}
}
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
_skipUpdate = true;
Password = AssociatedObject.Password;
_skipUpdate = false;
}
}
И использование:
<PasswordBox>
<i:Interaction.Behaviors>
<Behaviors:PasswordBehavior Password="{Binding Password, Mode=TwoWay}" />
</i:Interaction.Behaviors>
</PasswordBox>
0
Суть описанного метода состоит в том, чтобы не хранить пароль в открытом виде ни в каком из объектов, а получать его по требованию. В вашем же примере пароль будет находится в VM все время пока существует сама VM.
0
Если вас беспокоит вопрос безопасности, то можно вместо свойства PasswordBox.Password использовать PasswordBox.SecurePassword. Как вариант, можно реализовать IPasswordSupplier в Behavior'е, забиндить ViewModel.Password на Behavior и оставить в покое контейнер и контрол.
0
С SecureString не хочется связываться, потому что для дешифрации пароля нужно работать с неуправляемыми типами данных. Во втором варианте вы предлагаете избежать хранения пароля в открытом виде в классе PasswordBehavior вашего примера (т.к. он будет дешифроваться с помощью интерфейса), но после биндинга к свойству ViewModel он опять же будет храниться в открытом виде. Биндинг который в конечном итоге работает со свойством PasswordBox.Password нельзя использовать вообще.
0
View
ViewModel
А еще можно для взаимодействия ViewModel и View делать behavior'ы.
<PasswordBox Name="PasswordBox" PasswordChar="*" />
<Button Content="Login" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=PasswordBox}" IsDefault="True" />
ViewModel
private void OnLoginCommand(object commandParameter)
{
var password = ((PasswordBox)commandParameter).Password;
}
А еще можно для взаимодействия ViewModel и View делать behavior'ы.
-1
В данном решении ViewModel Жестко связан с View. В VM вообще не должно быть даже упоминания элементов управления.
0
Недавно была рецензия на книгу «Dependency Injection in .NET». Вам стоит её почитать.
В Вашем случае можно засетать
В Вашем случае можно засетать
IPasswordSupplier
в VM в методе OnStartup.0
Спасибо, рецензию я читал, а вот книгу пока еще нет. В моем случае действительно можно было сразу передать интерфейс в VM и тогда unity в самом VM вообще не нужен. Я описал более общий подход, который можно использовать в разных сценариях. Например, если ViewModel и View создаются в разных местах, или же View вообще явно не создается, а биндится в ресурсах:
В этом случае передать интерфейс в VM нет возможности.
<DataTemplate DataType="{x:Type my:LoginViewModel}">
<my:LoginControl />
</DataTemplate>
В этом случае передать интерфейс в VM нет возможности.
0
Если нет возможности использовать Constructor Injection, Вам придёться использовать контейнер как Service Locator внутри этой VM, а это уже попахивает.
0
я был очень вдохновлен философией MVVM и решил все будущие проекты писать исключительно с ее использованием.
А как Вы боритесь с жирной ViewModel? У нас ViewModel главной вьюхи настолько здоровая стала, что логику отвечающую за определенные действия, приходится пихать в partial классы :(
0
Как вариант элементы главного View можно сгрупировать в отдельные UserControl-ы и перенести логику связанную с ними в соответствующие ViewModel-ы, которые будут в виде свойств в главном ViewModel.
0
Можно вот так: Prism aka Composite WPF.
0
По-моему, основной способ борьбы с раздуванием ViewModel — следование принципу SRP и использование Dependency Injection.
0
Бороться с жирными вьюмоделями надо точно так же, как и с другими жирными классами. SOLID, в частности буква S.
Ещё помогает избегание реализации вызова PropertyChanged в сеттере каждого свойства, если вдуматься, то часто бывает, что в половине свойств это не нужно.
Ещё помогает избегание реализации вызова PropertyChanged в сеттере каждого свойства, если вдуматься, то часто бывает, что в половине свойств это не нужно.
0
Интересно за что автору в карму отрицательно капнули?
Неудачное на ваш взгляд решение и тем более данная статья по-моему не повод…
П.С.: мне изложенное решение не нравится тоже, если что.
Неудачное на ваш взгляд решение и тем более данная статья по-моему не повод…
П.С.: мне изложенное решение не нравится тоже, если что.
0
Судя по профилю у автора карма 2 и 2 голоса. Т.е. карму ему никто не портил. У него отрицательный рейтинг, т.к. минусовали статью. Статью минусовали, скорее всего, именно из-за того, что предлагаемое решение не оптимальное, и в комментариях описали почему.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Доступ к PasswordBox в условиях MVVM