none
多属性如何同时校验 RRS feed

  • 问题

  • Model类里面有两个int字段x和y,想实现这样的校验功能:

    1. x必须大于0;

    2. y必须大于0;

    3. x+y必须小于等于10.

    x y都绑定到了文本框,那么,在x校验的同时,如果x+y>10,如何把两个文本框都标红?

    2018年3月6日 2:28

答案

  • 你好,

    根据你的描述,我们可以使用IDataErrorInfo 来实现这样的需求,下面是一个简单的MVVM的例子,你可以参考一些.

    #View Model

    using System.ComponentModel;
    
    namespace WpfValid
    {
        public class ValidViewModel : INotifyPropertyChanged, IDataErrorInfo
        {
            private int x;
            public int X
            {
                get
                {
                    return x;
                }
                set
                {
                    x = value;
                    NotifyPropertyChanged("X");
                    NotifyPropertyChanged("Y");
                }
            }
    
            private int y;
            public int Y
            {
                get
                {
                    return y;
                }
                set
                {
                    y = value;
                    NotifyPropertyChanged("Y");
                    NotifyPropertyChanged("X");
                }
            }
            public string Error { get; private set; }
            public string this[string property]
            {
                get
                {
                    switch (property)
                    {
                        case "X":
                            if (X < 0)
                            {
                                return "X > 0";
                            }
                            if (X + Y > 10)
                            {
                                return "X + Y <= 10";
                            }
                            break;
                        case "Y":
                            if (Y < 0)
                            {
                                return "X > 0";
                            }
                            if (X + Y > 10)
                            {
                                return "X + Y <= 10";
                            }
                            break;
                    }
                    return null;
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            public void NotifyPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }

    #Xaml

    <Window x:Class="WpfValid.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:WpfValid"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel>
            <TextBox Height="20" x:Name="XTextBox" Text="{Binding X, Mode=TwoWay, ValidatesOnDataErrors=True}"  />
                <TextBox Height="20" x:Name="YTextBox"  Text="{Binding Y, Mode=TwoWay, ValidatesOnDataErrors=True}"  />
            </StackPanel>
        </Grid>
    </Window>

    #Code Behind

    using System.Windows;
    
    namespace WpfValid
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                ValidViewModel model = new ValidViewModel();
                model.X = 6;
                model.Y = 7;
                this.DataContext = model;
            }
        }
    }

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    2018年3月6日 6:05

全部回复

  • 你好,

    根据你的描述,我们可以使用IDataErrorInfo 来实现这样的需求,下面是一个简单的MVVM的例子,你可以参考一些.

    #View Model

    using System.ComponentModel;
    
    namespace WpfValid
    {
        public class ValidViewModel : INotifyPropertyChanged, IDataErrorInfo
        {
            private int x;
            public int X
            {
                get
                {
                    return x;
                }
                set
                {
                    x = value;
                    NotifyPropertyChanged("X");
                    NotifyPropertyChanged("Y");
                }
            }
    
            private int y;
            public int Y
            {
                get
                {
                    return y;
                }
                set
                {
                    y = value;
                    NotifyPropertyChanged("Y");
                    NotifyPropertyChanged("X");
                }
            }
            public string Error { get; private set; }
            public string this[string property]
            {
                get
                {
                    switch (property)
                    {
                        case "X":
                            if (X < 0)
                            {
                                return "X > 0";
                            }
                            if (X + Y > 10)
                            {
                                return "X + Y <= 10";
                            }
                            break;
                        case "Y":
                            if (Y < 0)
                            {
                                return "X > 0";
                            }
                            if (X + Y > 10)
                            {
                                return "X + Y <= 10";
                            }
                            break;
                    }
                    return null;
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            public void NotifyPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }

    #Xaml

    <Window x:Class="WpfValid.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:WpfValid"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel>
            <TextBox Height="20" x:Name="XTextBox" Text="{Binding X, Mode=TwoWay, ValidatesOnDataErrors=True}"  />
                <TextBox Height="20" x:Name="YTextBox"  Text="{Binding Y, Mode=TwoWay, ValidatesOnDataErrors=True}"  />
            </StackPanel>
        </Grid>
    </Window>

    #Code Behind

    using System.Windows;
    
    namespace WpfValid
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                ValidViewModel model = new ValidViewModel();
                model.X = 6;
                model.Y = 7;
                this.DataContext = model;
            }
        }
    }

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    2018年3月6日 6:05
  • IDataErrorInfo 并不能触发当前属性以外的Validation。因为系统调用的索引器传入参数永远是当前属性。

     public int X
            {
                get
                {
                    return x;
                }
                set
                {
                    x = value;
                    NotifyPropertyChanged("X");  调用索引器 property = “X”
                    NotifyPropertyChanged("Y");   调用索引器 property = “X”,不是“Y”
                }
            }

    2018年3月6日 6:10
  • 你好,

    你可以看我的效果图,是可以的.

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年3月6日 6:12
  • 谢谢您的答复,直接绑定到控件确实可以,我测试了。

    不知道您有没有使用过softfluent.Windows,可以动态的根据类的属性生成控件。

    现在用IDataErrorInfo的方式,发现无法在当前属性外调用其它属性的Validation,不知道您是否能帮忙看下原因。

    2018年3月6日 6:52
  • 你好,

    关于三方工具、控件的问题,建议在三方的轮坛,或者在github 直接问作者.

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年3月6日 7:15