如何禁用基于WPF验证的一些控件? [英] How do I disable some controls based on validation in 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 =Horizontal>
< 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屋!