In WPF, data binding enables you to hook a specific property in your data context (in my case, the view model) to a property on a user interface control. For example, the following XAML markup shows how the Text property on a TextBox can be bound to the FirstName property on the view model:
<TextBox Height="23"
Width="120"
Text="{Binding Path=FirstName, Mode=TwoWay}" />
As the Mode is set to TwoWay, any text changes by the user will result in the FirstName property being updated in the view model, likewise, any programmatic change to the FirstName view model property will result in the user interface being updated (provided that your view model implements the INotifyPropertyChanged interface and the setter of the FirstName property raises the OnPropertyChanged event). In my case, I had a PasswordBox control in my XAML markup that needed binding to a view model string property named Password. Initially I tried this in XAML:
Width="120"
Text="{Binding Path=FirstName, Mode=TwoWay}" />
<PasswordBox Name="userPasswordBox"
Height="23"
Width="120"
Password="{Binding Path=Password, Mode=OneWay}" />
However, the Visual Studio XAML designer immediately underlined the 'Password="{Binding...' line and stated the error:
Height="23"
Width="120"
Password="{Binding Path=Password, Mode=OneWay}" />
A 'Binding' cannot be set on the 'Password' property of type 'PasswordBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.As the binding error message alludes to, it turns out that the Password property on the PasswordBox control is a standard .NET CLR property and this was a deliberate security-based design decision by Microsoft to prevent plain text passwords from sitting around in memory. In my case however, having the password sit in memory wasn't an issue.
Of course, if the application I was working on wasn't using MVVM, then I could easily have picked up the user entered password in the code-behind in a button click event handler (e.g. this.userPasswordBox.Password would return the plain password). But because the application was adhering to MVVM, the code-behind was pretty much empty (except for the usual constructor boilerplate code). Instead, all of the UI "events" were being handled by the view model via command objects exposed as public properties. This therefore made retrieving the password from the PasswordBox and assigning it to the view model Password property an annoyingly interesting problem!
After doing a bit of research on the web, I found a couple of solutions.
- Pass the PasswordBox control to the view model: In this solution, the PasswordBox control itself is passed back to the view model via a command parameter (which is hooked up to the "OK" button). The method that handles the command then gets the PasswordBox instance via an object type parameter which can be cast back into a PasswordBox. You can then retrieve the password easily through the PasswordBox.Password property.
- Use attached properties to enable binding: In this solution, attached properties (a special type of dependency property) are created, enabling you to use them on the PasswordBox control and bind to your view model property.
The first solution above works but I wasn't too happy with passing a UI component to my view model - it violates the MVVM design pattern principle of decoupling the view from the view model. I went for the second option as it enabled binding to the PasswordBox.Password property (albeit indirectly) and didn't violate the use of MVVM in the process.
To get this working, take a look at the static PasswordBoxAssistant class on Samuel Jack's interesting blog. The class defines the attached properties that you can then use in your XAML markup, in my case, it resulted in the following markup:
<PasswordBox Name="userPasswordBox"
Height="23"
Width="120"
ap:PasswordBoxAssistant.BindPassword="true"
ap:PasswordBoxAssistant.BoundPassword=
"{Binding Path=Password,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
/>
As shown in the markup above, you'll need to import the namespace that the PasswordBoxAssistant class is defined in and add an alias to it (in my case "ap"). Having done that, it's finally just a case of using the attached properties to wire up the binding to your view model property.
Height="23"
Width="120"
ap:PasswordBoxAssistant.BindPassword="true"
ap:PasswordBoxAssistant.BoundPassword=
"{Binding Path=Password,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
/>
I will recommend anyone looking for Business loan to Le_Meridian they helped me with Four Million USD loan to startup my Quilting business and it's was fast When obtaining a loan from them it was surprising at how easy they were to work with. They can finance up to the amount of $500,000,000.000 (Five Hundred Million Dollars) in any region of the world as long as there 1.9% ROI can be guaranteed on the projects.The process was fast and secure. It was definitely a positive experience.Avoid scammers on here and contact Le_Meridian Funding Service On. lfdsloans@lemeridianfds.com / lfdsloans@outlook.com. WhatsApp...+ 19893943740. if you looking for business loan.
ReplyDeleteC Developer Blog >>>>> Download Now
ReplyDelete>>>>> Download Full
C Developer Blog >>>>> Download LINK
>>>>> Download Now
C Developer Blog >>>>> Download Full
>>>>> Download LINK
Very helpful and informative
ReplyDeleteCoding articles...