如何禁用基于WPF验证的一些控件? [英] How do I disable some controls based on validation in WPF?

查看:186
本文介绍了如何禁用基于WPF验证的一些控件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由TabControl组成的WPF应用程序。我为这个问题制作了一个简单的版本:


在第一个选项卡中,我有组合框填充数据网格。如果我在数据网格中选择了一行,它会绑定几个文本框,用户可以编辑它的内容。

我在datagrid中的对象实现了IDataErrorInfo接口和我的文本框ValidatesOnDataErrors = True在{binding}中设置。所以,如果我删除名称文本框的内容,它会变得无效(在文本框失去焦点之后):


所以我要么禁用左侧的控件,如果绑定的对象是无效的或我需要如果我点击左侧的控件,将焦点设置为无效的文本框。我没有找到适合的事件或绑定。所有的想法都赞赏。



这是我的XAML:

 < Window x:Class =WpfValidationTest.MainWindow
xmlns =http://schemas.microsoft.com/winfx/2006/xaml / presentation
xmlns:x =http://schemas.microsoft.com/winfx/2006/xaml
Title =MainWindowHeight =350Width =350>
< TabControl>
< TabItem Header =Tab 1>
< StackPanel Orientation =Horizo​​ntal>
< StackPanel Orientation =Vertical>
< ComboBox>
< ComboBox.Items>
< ComboBoxItem Content =Friends/>
< ComboBoxItem Content =Business/>
< /ComboBox.Items>
< / ComboBox>
< DataGrid Name =dgAutoGenerateColumns =False>
< DataGrid.Columns>
< DataGridTextColumn Header =NameBinding ={Binding Name}/>
< DataGridTextColumn Header =AddressBinding ={Binding Address}/>
< /DataGrid.Columns>
< / DataGrid>
< / StackPanel>

< StackPanel Orientation =VerticalWidth =200Margin =10,0,0,0>
< TextBlock Text =EditFontWeight =Bold/>
< TextBlock Text =Name:/>
< TextBox Text ={Binding Path = SelectedItem.Name,ElementName = dg,ValidatesOnDataErrors = True}/>
< TextBlock Text =Address:/>
< TextBox Text ={Binding Path = SelectedItem.Address,ElementName = dg,ValidatesOnDataErrors = True}/>
< / StackPanel>
< / StackPanel>
< / TabItem>

< TabItem Header =Tab 2>
< TextBlock Text =即使存在验证错误,用户也应该能够导航到此选项卡TextWrapping =Wrap/>
< / TabItem>
< / TabControl>

< / Window>

这里是后面的代码:

 使用System; 
using System.Collections.Generic;
使用System.Linq;
使用System.Text;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
使用System.ComponentModel;

命名空间WpfValidationTest
{
///< summary>
/// MainWindow.xaml的交互逻辑
///< / summary>
public partial class MainWindow:Window
{
public MainWindow()
{
InitializeComponent();

列表< Person> person = new List< Person>()
{
new Person(){Name =John Doe,Address =My street 203},
New Person(){Name = Jane Doe,地址=你的街道43}
};
dg.ItemsSource =个人;


$ b $ public class Person:INotifyPropertyChanged,IDataErrorInfo
{
public Event PropertyChangedEventHandler PropertyChanged;

public string Error
{
get {throw new NotImplementedException(); }


public string this [string columnName]
{
get
{
switch(columnName)
{
caseName:
if(string.IsNullOrEmpty(Name))
returnName must be entered;
break;
caseAddress:
if(string.IsNullOrEmpty(Address))
return必须输入地址;
break;
}
返回null;
}
}

private string _name;
public string Name
{
get {return _name; }
set
{
_name = value;
NotifyPropertyChanged(Name);
}
}

private string _address;
public string Address
{
get {return _address; }
set
{
_address = value;
NotifyPropertyChanged(Address);


$ b private void NotifyPropertyChanged(string propName)
{
if(PropertyChanged!= null)
PropertyChanged(this,new PropertyChangedEventArgs(PROPNAME));




$ div class =h2_lin>解决方案

您可以使用触发器来禁用控件

 < Style x:Key =disableOnValidation
BasedOn ={StaticResource {x:Type DataGrid}}
TargetType ={x:Type DataGrid}>
< Style.Triggers>
< DataTrigger Binding ={Binding ElementName = nameTextBox,Path = Validation.HasError}Value =True>
< Setter Propert =IsEnabledValue =False/>
< / DataTrigger>
< DataTrigger Binding ={Binding ElementName = addressTextbox,Path = Validation.HasError}Value =True>
< Setter Propert =IsEnabledValue =False/>
< / DataTrigger>
< / style>


I have a WPF application which consists of a TabControl. I have made a simple version of it for the purpose of this question:

In the first tab I have combobox which fills a datagrid. If I selected a row in the datagrid it gets bound a couple of textboxes and the user may edit its contents.

My objects in the datagrid implements the IDataErrorInfo interface and my textboxes has ValidatesOnDataErrors=True set in the {binding}. So if I erase the contents of the Name textbox it gets invalid (after the textbox loses focus):

Now, if it is invalid I don't want the user to be able to select another row in the datagrid, or select another row in the combobox (which would repopulate the datagrid). Basically I want the user to correct the name before he/she continues. Although, I would prefer if the user could switch tab.

So I either need to disable the controls to the left if the bound object is invalid or I need to set focus to the invalid textbox if I click on the controls to the left. I havn't found any suitable events or bindings for this. All ideas are appreciated.

Here is my XAML:

<Window x:Class="WpfValidationTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="350">
    <TabControl>
        <TabItem Header="Tab 1">
            <StackPanel Orientation="Horizontal">
                <StackPanel Orientation="Vertical">
                    <ComboBox>
                        <ComboBox.Items>
                            <ComboBoxItem Content="Friends"/>
                            <ComboBoxItem Content="Business"/>
                        </ComboBox.Items>
                    </ComboBox>
                    <DataGrid Name="dg" AutoGenerateColumns="False">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                            <DataGridTextColumn Header="Address" Binding="{Binding Address}" />
                        </DataGrid.Columns>
                    </DataGrid>
                </StackPanel>

                <StackPanel Orientation="Vertical" Width="200" Margin="10,0,0,0">
                    <TextBlock Text="Edit" FontWeight="Bold"/>
                    <TextBlock Text="Name:"/>
                    <TextBox Text="{Binding Path=SelectedItem.Name, ElementName=dg, ValidatesOnDataErrors=True}" />
                    <TextBlock Text="Address:"/>
                    <TextBox Text="{Binding Path=SelectedItem.Address, ElementName=dg, ValidatesOnDataErrors=True}" />
                </StackPanel>
            </StackPanel>
        </TabItem>

        <TabItem Header="Tab 2">
            <TextBlock Text="The user should be able to navigate to this tab even if there are validation errors" TextWrapping="Wrap" />
        </TabItem>
    </TabControl>

</Window>

And here is the code behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace WpfValidationTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            List<Person> persons = new List<Person>()
            {
                new Person(){Name="John Doe", Address="My street 203"},
                new Person(){Name="Jane Doe", Address="Your street 43"}
            };
            dg.ItemsSource = persons;
        }
    }

    public class Person : INotifyPropertyChanged, IDataErrorInfo
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get 
            {
                switch (columnName)
                {
                    case "Name":
                        if (string.IsNullOrEmpty(Name))
                            return "Name must be entered";
                        break;
                    case "Address":
                        if (string.IsNullOrEmpty(Address))
                            return "Address must be entered";
                        break;
                }
                return null;
            }
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }

        private string _address;
        public string Address
        {
            get { return _address; }
            set
            {
                _address = value;
                NotifyPropertyChanged("Address");
            }
        }

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

解决方案

You can use a trigger to disable the control

     <Style x:Key="disableOnValidation"
           BasedOn="{StaticResource {x:Type DataGrid}}"
           TargetType="{x:Type DataGrid}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding ElementName=nameTextBox, Path=Validation.HasError}" Value="True">
                <Setter Propert="IsEnabled" Value="False" />
            </DataTrigger>
            <DataTrigger Binding="{Binding ElementName=addressTextbox, Path=Validation.HasError}" Value="True">
                <Setter Propert="IsEnabled" Value="False" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

这篇关于如何禁用基于WPF验证的一些控件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆