如何在WPF中禁用一些基于验证的控件?
我有一个WPF应用程序,它由一个TabControl组成。为了回答这个问题,我做了一个简单的版本: 在第一个选项卡中,我有一个填充数据网格的组合框。如果我在datagrid中选择了一行,它会绑定几个文本框,用户可以编辑它的内容 datagrid中的My对象实现IDataErrorInfo接口,我的文本框在{binding}中设置了validateOnDaerRors=True。因此,如果我删除名称文本框的内容,它将变得无效(在文本框失去焦点后): 现在,如果无效,我不希望用户能够在datagrid中选择另一行,或者在combobox中选择另一行(这将重新填充datagrid)。基本上,我希望用户在继续之前更正名称。尽管如此,我还是希望用户可以切换选项卡 因此,如果绑定对象无效,我需要禁用左侧的控件;如果单击左侧的控件,我需要将焦点设置为无效文本框。我还没有找到任何合适的活动或绑定。非常感谢所有想法 这是我的XAML:如何在WPF中禁用一些基于验证的控件?,wpf,validation,focus,Wpf,Validation,Focus,我有一个WPF应用程序,它由一个TabControl组成。为了回答这个问题,我做了一个简单的版本: 在第一个选项卡中,我有一个填充数据网格的组合框。如果我在datagrid中选择了一行,它会绑定几个文本框,用户可以编辑它的内容 datagrid中的My对象实现IDataErrorInfo接口,我的文本框在{binding}中设置了validateOnDaerRors=True。因此,如果我删除名称文本框的内容,它将变得无效(在文本框失去焦点后): 现在,如果无效,我不希望用户能够在datag
<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>
下面是背后的代码:
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));
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用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;
使用系统组件模型;
命名空间WpfValidationTest
{
///
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
名单人员=新名单()
{
新人(){Name=“John Doe”,Address=“My street 203”},
新人(){Name=“Jane Doe”,Address=“Your street 43”}
};
dg.ItemsSource=人员;
}
}
公共类人员:INotifyPropertyChanged,IDataErrorInfo
{
公共事件属性更改事件处理程序属性更改;
公共字符串错误
{
获取{抛出新的NotImplementedException();}
}
公共字符串此[string columnName]
{
得到
{
开关(列名称)
{
案例“名称”:
if(string.IsNullOrEmpty(Name))
return“必须输入名称”;
打破
案例“地址”:
if(string.IsNullOrEmpty(Address))
返回“必须输入地址”;
打破
}
返回null;
}
}
私有字符串\u名称;
公共字符串名
{
获取{return\u name;}
设置
{
_名称=值;
NotifyPropertyChanged(“名称”);
}
}
私有字符串地址;
公共字符串地址
{
获取{return\u address;}
设置
{
_地址=值;
NotifyPropertyChanged(“地址”);
}
}
私有void NotifyPropertyChanged(字符串propName)
{
if(PropertyChanged!=null)
PropertyChanged(这是新PropertyChangedEventArgs(propName));
}
}
}
您可以使用触发器禁用控件
<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>
感谢Merlyn Morgan Graham添加这些图像。由于我是一名新会员,所以无法添加。谢谢adcool2007,它几乎成功了。我必须将绑定路径更改为(Validation.HasError),正如本文所述:另一个问题是,当IsEnabled设置为false时,datagrid的SelectedItem变为null。所以我改成了这样:用户可能仍然会在datagrid中使用tab键:-(@Björn您是否将SelectedItemin datagrid的绑定设置为Viewmodel属性,如SelectedItem={binding Path=MySelectedItem,Mode=TwoWay}
?我的简单示例中没有使用viewmodel,但我现在制作了一个viewmodel来尝试绑定表达式,但我仍然遇到相同的问题:当datagrid被禁用时,SelectedItem被设置为null,这使得我在viewmodel中的属性也为null。如果我将IshittesVisible设置为“False”,则不透明度设置为“0.5”和KeyboardNavigation.TabNavigation在数据触发器中设置为“无”,然后我会得到一个近似等于禁用datagrid的结果。我会将adcool2007的答案标记为已接受,因为他/她引导了我。谢谢。