views:

413

answers:

3

Hi!

I have a login form that contains a username textbox and a password box. I want the ok button to be enabled only when both the fields contain a value.

I have a converter that check for all the strings if they're null or empty. I placed a breakpoint on the first line of the Convert method, and it stops only when the MenuItem initializes, afterwords, i.e. when I change the text it doesn't. The following example works good, the problem is that the multibinding is not triggered when i change the text; it's only binded when initializing the form:

<!--The following is placed in the OK button-->
<Button.IsEnabled>
    <MultiBinding Converter="{StaticResource TrueForAllConverter}">
        <Binding ElementName="tbUserName" Path="Text"/>
        <Binding ElementName="tbPassword" Path="Password"/>
    </MultiBinding>
</Button.IsEnabled>

I think the issue is that you don't get notified when the remote binding source is changed (e.g. there is no an option to set UpdateTargetTrigger="PropertyChanged".

Any ideas?

A: 

Try setting the UpdateSourceTrigger to PropertyChanged and the Mode to TwoWay. This will cause the property to be updated as you type. Not sure if this will work with your converter, though.

Jerry Bullard
I tried the above and it doesn't work.
Shimmy
A: 
Private Sub tb_Changed(sender As Object, e As RoutedEventArgs) _
        Handles tbUsername.TextChanged, _
                tbPassword.PasswordChanged
    btnOk.IsEnabled = tbUsername.Text.Length > 0 _
              AndAlso tbPassword.Password.Length > 0
End Sub
Shimmy
+2  A: 

I would suggest you look into command binding. A command can enable or disable your Login button automatically depending on some condition (ie. user name and password is not empty).

public static RoutedCommand LoginCommand = new RoutedCommand();

private void CanLoginExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = !string.IsNullOrEmpty(_userInfo.UserName) && !string.IsNullOrEmpty(_userInfo.Password);
    e.Handled = true;
}

private void LoginExecute(object sender, ExecutedRoutedEventArgs e)
{
    MessageBox.Show("Loging in...");
    // Do you login here.
    e.Handled = true;
}

XAML command binding will look something like this

<TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}" />
<Button Command="local:LoginWindow.LoginCommand" >Login</Button>

To register the command in XAML

<Window.CommandBindings>
    <CommandBinding Command="local:LoginWindow.LoginCommand" CanExecute="CanLoginExecute" Executed="LoginExecute" />
</Window.CommandBindings>

Or in code behind

public LoginWindow()
{
    InitializeComponent();

    CommandBinding cb = new CommandBinding(LoginCommand, CanLoginExecute, LoginExecute);
    this.CommandBindings.Add(cb);
}

More readigin here.

Tri Q
+1... it may save people a bit of searching if you also mention that the reason why command binding is the way to do it is because the *Password* property on the *PasswordBox* is not a dependency property and it doesn't notify that it has changed. [Here is a good blog post](http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html) on this particular issue.
slugster