【问题标题】:How do I disable some controls based on validation in WPF?如何根据 WPF 中的验证禁用某些控件?
【发布时间】:2011-12-30 04:56:02
【问题描述】:

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

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

我在数据网格中的对象实现了 IDataErrorInfo 接口,并且我的文本框在 {binding} 中设置了 ValidatesOnDataErrors=True。因此,如果我删除 Name 文本框的内容,它会变得无效(在文本框失去焦点之后):

现在,如果它无效,我不希望用户能够在数据网格中选择另一行,或在组合框中选择另一行(这将重新填充数据网格)。基本上我希望用户在他/她继续之前更正名称。不过,如果用户可以切换标签,我会更喜欢。

因此,如果绑定的对象无效,我要么需要禁用左侧的控件,要么如果单击左侧的控件,我需要将焦点设置到无效的文本框。我还没有找到任何合适的事件或绑定。感谢所有想法。

这是我的 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>

下面是代码:

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));
        }
    }
}

【问题讨论】:

  • 感谢 Merlyn Morgan-Graham 添加图片。我是新会员,无法添加。

标签: wpf validation focus


【解决方案1】:

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

     <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>

【讨论】:

  • 谢谢 adcool2007,它几乎成功了。我不得不将绑定路径更改为 (Validation.HasError),正如这篇文章所说:stackoverflow.com/questions/4055226/… 另一个问题是,当 IsEnabled 设置为 false 时,数据网格的 SelectedItem 变为空。所以我改为: 用户可以通过标签进入数据网格:-(
  • @Björn 您是否将 SelectedItemin dataGrid 的绑定设置为您的 Viewmodel 属性,例如SelectedItem={Binding Path=MySelectedItem,Mode=TwoWay} ??
  • 我没有在我的简单示例中使用视图模型,但我现在制作了一个视图模型来尝试您的绑定表达式,但我仍然遇到同样的问题:当数据网格被禁用时,SelectedItem 被设置为 null使我在视图模型中的属性也为空。
  • 如果我在数据触发器中将 IsHitTestVisible 设置为“False”,将 Opacity 设置为“0.5”,将 KeyboardNavigation.TabNavigation 设置为“None”,那么我得到的结果大致相当于禁用数据网格。我将 adcool2007 的答案标记为已接受,因为他/她引导我这样做。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-12
  • 2016-12-21
  • 2014-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多