WPF中的绑定验证

时间:2018-09-26 18:41:50

标签: c# wpf

我在WPF中第一次进入绑定验证。我正在使用Microsoft Docs中的教程指南来验证输入到文本框中的数据。我相信我理解并正确执行了该过程,但是验证仍然无法进行。我不确定文本框上的绑定是否错误,或者ValidationRule是否存在问题。任何帮助将不胜感激。

下面是带有验证器规则的类。

class NumberCansValidationRule : ValidationRule
{
    private int _min;
    private int _max;

    public int Min
    {
        get { return _min; }

        set { _min = value; }
    }

    public int Max
    {
        get { return _max; }

        set { _max = value; }
    }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        int numCans = 0;

        try
        {
            if (((string)value).Length > 0)
            {
                numCans = Int32.Parse((string)value);
            }
        }
        catch (Exception e)
        {
            return new ValidationResult(false, "Illegal characters or " + e.Message);
        }


        if ((numCans < Min) || (numCans > Max))
        {
            return new ValidationResult(false, "Number of cans must be between: " + Min + " - " + Max + ".");
        }
        else
        {
            return new ValidationResult(true, null);
        }
    }
}

这是我的主要课程。

public partial class MainWindow : Window
{
    public ObservableCollection<Drinks> SomeDrinks { get; private set; }

    public MainWindow()
    {
        InitializeComponent();

        SomeDrinks = new ObservableCollection<Drinks>();

        SomeDrinks.Add(new Drinks("Soda", "Pepsi", 5));         
        SomeDrinks.Add(new Drinks("Tea", "Lemon", 3));
        SomeDrinks.Add(new Drinks("Caffinated", "Coffee", 0));
        SomeDrinks.Add(new Drinks("Other", "Water", 0));

        DrinksListBox.ItemsSource = SomeDrinks;
        DrinkTypeComboBox.ItemsSource = SomeDrinks;
    }

    private void CmdDeleteDrink_Clicked(object sender, RoutedEventArgs e)
    {
        Button cmd = (Button)sender;

        if (cmd.DataContext is Drinks deleteDrink)
        {
            SomeDrinks.Remove(deleteDrink);
        }
    }

    private void CmdAddDrink_Clicked(object sender, RoutedEventArgs e)
    {
        string typeSelection = ((Drinks)DrinkTypeComboBox.SelectedItem).Type;

        int canNum = Int32.Parse(NumberCansTextBox.Text);

        SomeDrinks.Add(new Drinks(typeSelection, DrinkNameTextBox.Text, canNum)
        {
            IsUserDefined = true
        });
    }
}

public class Drinks
{
    private string type;
    private string name;
    private int numCans;

    public Drinks(string type, string name, int numCans)
    {
        this.type = type;
        this.name = name;
        this.numCans = numCans;
    }

    public bool IsUserDefined { get; set; }

    public string Type
    {
        get { return type; }

        set
        {
            if (type != value)
            {
                type = value;
            }
        }
    }

    public string Name
    {
        get { return name; }

        set
        {
            if (name != value)
            {
                name = value;
            }
        }
    }

    public int NumberOfCans
    {
        get { return numCans; }

        set
        {
            if (numCans != value)
            {
                numCans = value;
            }
        }
    }
}

我的XAML在这里。

<Window x:Class="WpfApp1.MainWindow"
    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:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVis"/>

    <ControlTemplate x:Key="validationTemplate">
        <DockPanel>
            <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
            <AdornedElementPlaceholder/>
        </DockPanel>
    </ControlTemplate>

    <Style x:Key="textStyleTextBox" TargetType="TextBox">
        <Setter Property="Foreground" Value="#333333" />
        <Setter Property="MaxLength" Value="40" />
        <Setter Property="Width" Value="392" />
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <ListBox x:Name="DrinksListBox" HorizontalAlignment="Center" Height="325" Width="275" Margin="0,0,0,0" VerticalAlignment="Center" Grid.Column="0" ItemsSource="{Binding SomeDrinks}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid Margin="0,2">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Type}" Width="80"  Margin="0,0,10,0" Grid.Column="0"/>
                    <TextBlock Text="{Binding Name}" Width="80"  Margin="0,0,10,0" Grid.Column="1" HorizontalAlignment="Left"/>
                    <TextBlock Text="{Binding NumberOfCans}" Width="80"  Margin="0,0,10,0" Grid.Column="2" HorizontalAlignment="Left"/>
                    <Button x:Name="DrinkDeleteButton" Content="Delete" Visibility="{Binding Path=IsUserDefined, Converter={StaticResource BoolToVis}}" Click="CmdDeleteDrink_Clicked" HorizontalAlignment="Left" Grid.Column="3"/>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <TextBox x:Name="DrinkNameTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="45" Margin="0,0,0,100" TextWrapping="Wrap" Text="Enter Drink Name" VerticalAlignment="Center" Width="240" FontSize="20" VerticalContentAlignment="Center"/>
    <TextBox x:Name="NumberCansTextBox" Style="{StaticResource textStyleTextBox}" Grid.Column="1" HorizontalAlignment="Left" Height="45" Margin="0,0,0,150" VerticalAlignment="Bottom" Width="240" FontSize="20" VerticalContentAlignment="Center">
        <TextBox.Text>
            <Binding Path="NumberOfCans" UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                    <local:NumberCansValidationRule Min="0" Max="10"/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
    <ComboBox x:Name="DrinkTypeComboBox" Grid.Column="1" HorizontalAlignment="Left" Margin="0,47,0,0" VerticalAlignment="Top" Width="240" Height="45" ItemsSource="{Binding Drinks,  Mode=OneWay}" DisplayMemberPath="Type" FontSize="20"/>
    <Button x:Name="AddDrinkButton" Content="Add Drink" Grid.Column="1" HorizontalAlignment="Right" Margin="0,0,10,100" VerticalAlignment="Center" Width="100" Height="45" Click="CmdAddDrink_Clicked"/>
</Grid>

1 个答案:

答案 0 :(得分:0)

首先您需要添加

<Window.Resources>
    <local:Drinks x:Key="Drink"/>
...
</Window.Resources>
...
<Binding Path="NumberOfCans" UpdateSourceTrigger="PropertyChanged"  Source="{StaticResource Drink}">
...

和没有参数的构造函数

public Drinks()
{
}