如何根据用户在文本框中输入的文本进行验证来绑定标签的可见性和内容?

时间:2014-10-30 12:26:21

标签: wpf mvvm data-binding routed-commands

我正在编写简单的应用程序。 UI有两个文本框,用于用户名和密码,以及用于提交信息的按钮。我想使用路由命令而不是buttonclick事件。

用户名只能包含字母数字字符,如果用户输入任何其他特殊字符,则应显示一个标签,表示输入了无效字符。所以我想根据在Username文本框字段上完成的验证来绑定该标签的可见性和内容。

以下是我所制作的代码,但它没有按预期工作。任何人都可以帮助我在哪里做错了吗?

在我的主窗口

下面
using System.Windows;
using System.Windows.Input;
using System.ComponentModel;


namespace ExcelUtility
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    ViewModel viewModelObj = new ViewModel();
    public MainWindow()
    {
        InitializeComponent();
    }

    void navigatePageExecuted(object target, ExecutedRoutedEventArgs e)
    {
        SubmitUserDetails(txtUserName.Text + ";" + txtPassword);
    }

    void navigatePageCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
         if (!string.IsNullOrWhiteSpace(txtUserName.Text))
        {
            viewModelObj.Username = txtUserName.Text;
        }
        e.CanExecute = viewModelObj.VaidUserName;        }

    private void SubmitUserDetails(string credentials)
    {
        this.Cursor = Cursors.Wait;
        prgValidate.Visibility = Visibility.Visible;
        MainGrid.IsEnabled = false;
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.RunWorkerAsync(credentials);
    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        prgValidate.Visibility = Visibility.Collapsed;
        string Result = (string)e.Result;
        MessageBox.Show(Result); //Here I need to call some other functions based on return value for simplicity i have changed
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        string[] credentials = e.Argument.ToString().Split(';');
        e.Result = viewModelObj.validateCredentials(credentials[0], credentials[1]);
    }
}
}

这是我的xaml

<Window x:Class="ExcelUtility.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ExcelUtility"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:BoolToVisibleOrHidden x:Key="BoolToVisibilityConverter"/>
</Window.Resources>
<Window.CommandBindings>
    <CommandBinding Command="{x:Static local:CommandsLibrary.navigatePageCommand}" Executed="navigatePageExecuted" CanExecute="navigatePageCanExecute"/>
</Window.CommandBindings>
<Grid Name="MainGrid">
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="40,44,0,0" Name="tbUserName" Text="Username" VerticalAlignment="Top" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="136,42,0,0" Name="txtUserName" VerticalAlignment="Top" Width="163" Text="{Binding Username, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="138,19,0,0" Name="tbNotify" Text="{Binding Notification, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="161" Visibility="{Binding NotVaidUserName,Converter={StaticResource BoolToVisibilityConverter}}" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="138,98,0,0" Name="txtPassword" VerticalAlignment="Top" Width="161" />
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="44,107,0,0" Name="tbPassword" Text="Password" VerticalAlignment="Top" Width="65" />
    <Button Command="{x:Static local:CommandsLibrary.navigatePageCommand}" Content="Submit" Height="23" HorizontalAlignment="Left" Margin="172,167,0,0" Name="btnSubmit" VerticalAlignment="Top" Width="109" />
    <ProgressBar Height="24" IsIndeterminate="True" Visibility="Collapsed"  HorizontalAlignment="Left" Margin="52,232,0,0" Name="prgValidate" VerticalAlignment="Top" Width="257" />
</Grid>
</Window>

这是我的viewModel

using System;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Windows.Data;
using System.Windows;

namespace ExcelUtility
{
  public class ViewModel
  {
    public event PropertyChangedEventHandler PropertyChanged;
    private bool _notVaidUserName;
    public bool NotVaidUserName
    {
        get { return _notVaidUserName; }
        set
        {
            _notVaidUserName = value;
            RaisePropertyChanged("NotVaidUserName");
        }
    }

    private string notification;
    public string Notification
    {
        get
        {
            return notification;
        }
        set
        {
            if (notification != value)
            {
                notification = value;
                RaisePropertyChanged("Notification");
            }
        }
    }

    private string username;
    public string Username
    {
        get
        {
            return username;
        }
        set
        {
            if (username != value)
            {
                username = value;
                NotVaidUserName = VaidateUserName(username);
                RaisePropertyChanged("Username");
            }
        }
    }

    public bool VaidateUserName(string strUsername)
    {
        bool bValidUserName = false;            
        if (!string.IsNullOrWhiteSpace(strUsername))
        {
            if (new Regex(@"^[a-zA-Z0-9]*$").IsMatch(strUsername))
            {
                bValidUserName = true;
                if (strUsername.Length > 7)
                {
                    Notification = "Max allowed key length is 6";
                    bValidUserName = false;
                }
            }
            else
            {
                Notification = "No special characters allowed";
            }
        }
        return bValidUserName;
    }

    public string validateCredentials(string Username, string Password)
    {
        return "Valid Credentials";
    }

    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

class BoolToVisibleOrHidden : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        object returnvalue = new object();
        returnvalue = (bool)value ? Visibility.Visible : parameter != null ? Visibility.Collapsed : Visibility.Hidden;
        return returnvalue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (Visibility)value == Visibility.Visible;
    }
}
}

3 个答案:

答案 0 :(得分:0)

首先定义两个属性,如下所示:

private bool isValid = true;
    public bool IsValid
    {
        get
        {
            return isValid;
        }
        set
        {
            if (isValid != value)
            {
                isValid = value;
                OnPropertyChanged("IsValid");
            }
        }
    }
    private string username;
    public string Username
    {
        get
        {
            return username;
        }
        set
        {
            if(username != value)
            {
                username = value;
                IsValid = ValidateForSpecialCharacters(username);
                OnPropertyChanged("Username");
            }
        }
    }

然后将它们绑定到您的xaml,如下所示:

    <TextBlock Text="Username contains special characters."
               Visibility="{Binding IsValid,Converter={StaticResource BoolToVisibilityConverter}}" />
    <TextBox Text="{Binding Username, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />

PS:不要忘记实现BoolToVisibility转换器类和ValidateForSpecialCharacter方法。我想你可以自己处理。顺便说一句,如果我是你,我会用ValidationRule代替这种方式。

希望得到这个帮助。

答案 1 :(得分:0)

您必须创建一个boolToVis转换器,它将False转换为折叠,将True转换为可见。

在此之后,您可以将bool值绑定到项目的visibility属性。

这是转换器(您可以将它放在一个文件中并从xaml调用它):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace yourNamespace.ViewModel
{
    [ValueConversion(typeof(bool), typeof(bool))]
    public class InverseBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter,  
           System.Globalization.CultureInfo culture)
        {
            if (value is bool)
            {
                return !(bool)value;
            }
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter,  
           System.Globalization.CultureInfo culture)
        {
            if (value is bool)
            {
                return !(bool)value;
            }
            return value;
        }
    }
}

然后,从你的xaml,在文件的开头:

<UserControl.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVis"/>
</UserControl.Resources>

或者如果您使用窗口:

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>

然后,最后,在你的textBox中:

<dxe:TextEdit Visibility="{Binding YOURBOOLFLAG, Converter={StaticResource BoolToVis}}" EditValue="TextHere"/>

(TextEdit是一个devexpress元素;你也可以用同样的方式使用经典的textBox)

这样,当您看到文本不正确时,可以将bool标志设置为false并隐藏元素。

答案 2 :(得分:0)

您可以简单地实现一个检查用户名字符的转换器,如下所示:

class VisibilityConverter:IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var rgx = new Regex(@"^[a-zA-Z0-9]*$");
        if (value == null) return Visibility.Hidden;
        return (rgx.IsMatch(value.ToString()))?Visibility.Hidden:Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

不要忘记将转换器添加到窗口资源

 <Window.Resources>
    <conv:VisibilityConverter x:Key="VisibilityConverter"/>
</Window.Resources>

最后在UI中使用该转换器来检查在textBox中输入的字符串

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="50"/>
        <RowDefinition Height="50"/>
        <RowDefinition Height="50"/>
        <RowDefinition Height="50"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <TextBlock Text="Username" Grid.Column="0" Grid.Row="0"/>
    <TextBlock Text="Password" Grid.Column="0" Grid.Row="1"/>   
    <TextBox  Grid.Column="1" Grid.Row="0" Text="{Binding Username,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <TextBox  Grid.Column="1" Grid.Row="1" Text="{Binding Password,Mode=TwoWay}"/>      
    <Button Content="login" IsEnabled="{Binding Username,Converter={StaticResource VisibilityConverter},Mode=TwoWay}" Grid.Column="1" Grid.Row="2"/>
    <TextBlock Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Text="invalid characters entered"  VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="{Binding Username,Converter={StaticResource VisibilityConverter}}"></TextBlock>

</Grid>