Dimitri Dimitri - 3 months ago 14
C# Question

Attachable property not found in type with WPF Password Binding

I've recently discovered that you should bind passwords in WPF. I found my answer to my problem for my login window, but I'm having a hard time using my helper class to solve the binding problem:

PasswordHelper
. This class is in one of my project's folder called
Utils
.

Here's part of my XAML code:

<Window x:Class="IPdevices.LoginWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:IPdevices"
xmlns:utils="clr-namespace:IPdevices.Utils;assembly=Utils"
mc:Ignorable="d"
Title="IPDevices" Height="451" Width="397.5" Icon="logo3_q2J_icon.ico">


notice the
xmlns:utils="clr-namespace:IPdevices.Utils;assembly=Utils"


My password box is now

<PasswordBox utils:PasswordHelper.BindPassword="true" utils:PasswordHelper.BoundPassword="{Binding Path=NetworkPassword, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />


However, this doesn't compile because it's screaming:

"The attachable property 'BindPassword' was not found in type 'PasswordHelper'."

It's also screaming:

"The name 'PasswordHelper' does not exist in the namespace 'clr-namespace;IPdevices.Uitls;assembly=Utils'"

And here's this
PasswordHelper
class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace IPdevices.Utils
{
public static class PasswordHelper
{
public static readonly DependencyProperty BoundPassword =
DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordHelper), new PropertyMetadata(string.Empty, OnBoundPasswordChanged));

public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(
"BindPassword", typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false, OnBindPasswordChanged));

private static readonly DependencyProperty UpdatingPassword =
DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false));

private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PasswordBox box = d as PasswordBox;

// only handle this event when the property is attached to a PasswordBox
// and when the BindPassword attached property has been set to true
if (d == null || !GetBindPassword(d))
{
return;
}

// avoid recursive updating by ignoring the box's changed event
box.PasswordChanged -= HandlePasswordChanged;

string newPassword = (string)e.NewValue;

if (!GetUpdatingPassword(box))
{
box.Password = newPassword;
}

box.PasswordChanged += HandlePasswordChanged;
}

private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
// when the BindPassword attached property is set on a PasswordBox,
// start listening to its PasswordChanged event

PasswordBox box = dp as PasswordBox;

if (box == null)
{
return;
}

bool wasBound = (bool)(e.OldValue);
bool needToBind = (bool)(e.NewValue);

if (wasBound)
{
box.PasswordChanged -= HandlePasswordChanged;
}

if (needToBind)
{
box.PasswordChanged += HandlePasswordChanged;
}
}

private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox box = sender as PasswordBox;

// set a flag to indicate that we're updating the password
SetUpdatingPassword(box, true);
// push the new password into the BoundPassword property
SetBoundPassword(box, box.Password);
SetUpdatingPassword(box, false);
}

public static void SetBindPassword(DependencyObject dp, bool value)
{
dp.SetValue(BindPassword, value);
}

public static bool GetBindPassword(DependencyObject dp)
{
return (bool)dp.GetValue(BindPassword);
}

public static string GetBoundPassword(DependencyObject dp)
{
return (string)dp.GetValue(BoundPassword);
}

public static void SetBoundPassword(DependencyObject dp, string value)
{
dp.SetValue(BoundPassword, value);
}

private static bool GetUpdatingPassword(DependencyObject dp)
{
return (bool)dp.GetValue(UpdatingPassword);
}

private static void SetUpdatingPassword(DependencyObject dp, bool value)
{
dp.SetValue(UpdatingPassword, value);
}
}
}


I've tried cleaning, rebuilding, double-checking everything but simply won't compile. Any insight?

Answer

This class is in one of my project's folder called Utils.

If that means that the class is in the same project as the WPF application that contains the XAML, then that implies that your xmlns is probably wrong.

For the current project it should be:

xmlns:utils="clr-namespace:IPdevices.Utils;assembly="

or

xmlns:utils="clr-namespace:IPdevices.Utils"