DataBinding on properties without setting

How can I bind data to a property only with a getter and without a setter to access it from a view model in wpf? I work with PasswordBox and want to bind its SecureString property to the ViewModel property. How can i do this?

+4
source share
3 answers

I use this class and System.Windows.Interactivity to access properties without setting:

 public sealed class PropertyManager : TriggerAction<FrameworkElement> { #region Fields private bool _bindingUpdating; private PropertyInfo _currentProperty; private bool _propertyUpdating; #endregion #region Dependency properties /// <summary> /// Identifies the <see cref="Binding" /> dependency property. /// </summary> public static readonly DependencyProperty BindingProperty = DependencyProperty.Register("Binding", typeof(object), typeof(PropertyManager), new PropertyMetadata((o, args) => { var propertyManager = o as PropertyManager; if (propertyManager == null || args.OldValue == args.NewValue) return; propertyManager.TrySetProperty(args.NewValue); })); /// <summary> /// Identifies the <see cref="SourceProperty" /> dependency property. /// </summary> public static readonly DependencyProperty SourcePropertyProperty = DependencyProperty.Register("SourceProperty", typeof(string), typeof(PropertyManager), new PropertyMetadata(default(string))); /// <summary> /// Binding for property <see cref="SourceProperty" />. /// </summary> public object Binding { get { return GetValue(BindingProperty); } set { SetValue(BindingProperty, value); } } /// <summary> /// Name property to bind. /// </summary> public string SourceProperty { get { return (string)GetValue(SourcePropertyProperty); } set { SetValue(SourcePropertyProperty, value); } } #endregion #region Methods /// <summary> /// Invokes the action. /// </summary> /// <param name="parameter"> /// The parameter to the action. If the action does not require a parameter, the parameter may be /// set to a null reference. /// </param> protected override void Invoke(object parameter) { TrySetBinding(); } /// <summary> /// Tries to set binding value. /// </summary> private void TrySetBinding() { if (_propertyUpdating) return; PropertyInfo propertyInfo = GetPropertyInfo(); if (propertyInfo == null) return; if (!propertyInfo.CanRead) return; _bindingUpdating = true; try { Binding = propertyInfo.GetValue(AssociatedObject, null); } finally { _bindingUpdating = false; } } /// <summary> /// Tries to set property value. /// </summary> private void TrySetProperty(object value) { if (_bindingUpdating) return; PropertyInfo propertyInfo = GetPropertyInfo(); if (propertyInfo == null) return; if (!propertyInfo.CanWrite) return; _propertyUpdating = true; try { propertyInfo.SetValue(AssociatedObject, value, null); } finally { _propertyUpdating = false; } } private PropertyInfo GetPropertyInfo() { if (_currentProperty != null && _currentProperty.Name == SourceProperty) return _currentProperty; if (AssociatedObject == null) throw new NullReferenceException("AssociatedObject is null."); if (string.IsNullOrEmpty(SourceProperty)) throw new NullReferenceException("SourceProperty is null."); _currentProperty = AssociatedObject .GetType() .GetProperty(SourceProperty); if (_currentProperty == null) throw new NullReferenceException("Property not found in associated object, property name: " + SourceProperty); return _currentProperty; } #endregion } 

To use this class in XAML, you need to add a reference to the System.Windows.Interactivity library and add this namespace:

 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:behaviors="clr-namespace:YOUR NAMESPACE WHERE YOU PUT THE PropertyManager CLASS" 

You also need to specify the event that will be updated, in this case PasswordChanged and specify the property that you want to bind, in this case Password :

 <PasswordBox> <i:Interaction.Triggers> <i:EventTrigger EventName="PasswordChanged"> <behaviors:PropertyManager Binding="{Binding Path=MyPasswordProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SourceProperty="Password" /> </i:EventTrigger> </i:Interaction.Triggers> </PasswordBox> 

This class is universal and can work with any of the properties, also supports two-way binding.

+1
source

bind in xaml:

 <PasswordBox Text="{Binding SecureString, Mode=OneWay}"... 

if you do not want it to change from xaml binding

 public string SecureString { get { return _secureString;} private set { if(_secureString == value) return; _secureString = value; RaisePropertyChanged(() => SecureString); } public void SetSecureString(string newSecureString) { SecureString = newSecureString; } 

The consumer of your ViewModel should be able to install SecureString , although this method.

0
source

You can associate with Get only property by setting the binding mode to OneWay according to your binding -

 <PasswordBox Text="{Binding SecureString, Mode=OneWay}" 
0
source

Source: https://habr.com/ru/post/1495198/


All Articles