【问题标题】:Styling the Validation Error on WPF DataGridCell在 WPF DataGridCell 上设置验证错误的样式
【发布时间】:2010-09-30 15:12:14
【问题描述】:

我正在尝试更改 DataGridCell 出现错误内容时的显示方式。默认情况下,它在遇到错误时具有白色背景和红色边框。但是,似乎我设置此类的 Validation.ErrorTemplate 的尝试被忽略了,我在 Validation.HasError 属性上的触发器也是如此。重现问题所需的所有代码都位于下面;我完全无法让 WPF 将任何类型的样式应用于错误的单元格。有没有人看到这里的问题或有潜在的解决方法?

APP.XAML

<Application.Resources>
        <ControlTemplate x:Key="ErrorTemplate">
            <DockPanel>
                <TextBlock Text="Busted!"/>
                <AdornedElementPlaceholder/>
            </DockPanel>
        </ControlTemplate>
        <Style x:Key="{x:Type WpfToolkit:DataGridCell}" TargetType="{x:Type WpfToolkit:DataGridCell}">
            <Style.Setters>
                <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate}"/>
                <Setter Property="Background" Value="Green"/>
            </Style.Setters>
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="Background" Value="Red"/>
                    <Setter Property="ToolTip" Value="Doh!"/>
                </Trigger>
            </Style.Triggers>

        </Style>
    </Application.Resources>

MainWindow.xaml

<Grid>

        <WpfToolkit:DataGrid ItemsSource="{Binding Path=MyItems, ValidatesOnDataErrors=True}" AutoGenerateColumns="False">
            <WpfToolkit:DataGrid.Columns>
                <WpfToolkit:DataGridTextColumn Header="Wheel Count" Binding="{Binding WheelCount, ValidatesOnDataErrors=True}"/>
                <WpfToolkit:DataGridTextColumn Header="Car Colour" Binding="{Binding Color, ValidatesOnDataErrors=True}"/>
            </WpfToolkit:DataGrid.Columns>
        </WpfToolkit:DataGrid>
    </Grid>

绑定的类是

Car.cs

class Car : IDataErrorInfo, INotifyPropertyChanged
    {
        public Car(int numWheels, string Color)
        {
            _color = Color;
            _wheelCount = numWheels;
        }

        private string _color;
        public string Color
        {
            get
            {
                return _color;
            }
            set
            {
                _color = value;
                if (value.Length > 10)
                {
                    //Warning
                }
                if (value.Length > 20)
                {
                    //Error
                }
                PropChanged("Color");

            }
        }

        private int _wheelCount;
        public int WheelCount
        {
            get
            {
                return _wheelCount;
            }
            set
            {
                _wheelCount = value;
                if (value != 4)
                {
                    AddError("WheelCount", "There should be 4 wheels on the car!");
                }
                else
                    this.ClearError("WheelCount");
                PropChanged("WheelCount");

            }
        }

        public void AddError(string propName, string errorMessage)
        {
            if (myErrors.ContainsKey(propName))
                myErrors.Remove(propName);
            myErrors.Add(propName, errorMessage);
            PropChanged(propName);
            PropChanged("Error");
        }

        public void ClearError(string propName)
        {
            if (myErrors.ContainsKey(propName))
                myErrors.Remove(propName);
        }

        private Dictionary<string, string> myErrors = new Dictionary<string, string>();

        public string Error
        {
            get
            {
                StringBuilder myError = new StringBuilder("Errors");
                foreach (KeyValuePair<string,string> currentErr in myErrors)
                {
                    myError.AppendLine(currentErr.Key + ":" + currentErr.Value);
                }
                return myError.ToString();
            }
        }

        public string this[string columnName]
        {
            get
            {
                if (!myErrors.ContainsKey(columnName))
                    return null;
                else
                    return myErrors[columnName];
            }
        }

        public void PropChanged(string propName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

视图的“ViewModel”是 CarVM:

CarVM.cs

 class CarVM
    {
        public CarVM()
        {
            for (int currentCar = 0; currentCar < 20; currentCar++)
            {
                myCars.Add(new Car(4, "Red"));
            }
            MyItems = (CollectionView)CollectionViewSource.GetDefaultView(myCars);
        }
        private List<Car> myCars = new List<Car>();
        public CollectionView MyItems
        {
            get;
            private set;
        }
    }

而且窗口中的代码很简单:

MainWindow.Xaml.Cs

 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new CarVM();
        }
    }

【问题讨论】:

  • 澄清一下;用户通过网格界面编辑属性时出现错误;不在上面的实际代码中。
  • 见我的comment

标签: .net wpf validation styles


【解决方案1】:

DataGrid 列的样式很难设置,因为 DataContext 在创建和应用样式时并不是您所期望的。请参阅this article,尤其是“使用 DataGridColumn.ElementStyle 和 DataGridColumn.EditingElementStyle 设置单元格内容的属性。”

【讨论】:

  • 这些东西适用于 DataGridColumn 样式;如果我只想更改一个单元格的外观怎么办?
  • 我不确定是否有办法设置单个单元格的样式,超出列中所有单元格的编辑和非编辑状态。该样式适用于单元格,但列中的所有单元格的样式都相同。
  • 无法为单个 DataGridCell 设置样式令人失望,但很高兴知道。
  • 链接好像坏了
【解决方案2】:

您可以尝试使用throw new ArgumentException 代替AddError 来确认吗?

以下条件是否失败?轮数和颜色都不一样

        for (int currentCar = 0; currentCar < 20; currentCar++)
        {
            myCars.Add(new Car(4, "Red"));
        }

HTH

【讨论】:

  • 我知道正在应用错误条件,因为边框变红了。没有应用的是我的自定义模板。
  • @GWLlosa 在实际代码中,您能否检查它是否有密钥? x:Key="{x:Type WpfToolkit:DataGridCell}" 它不应该有 x:Key。否则,如您所知,DataGridCell 将无法应用此样式。你已经指定了TargetType,我猜这应该足够了。如果您指定了x:Key,请将其删除并检查。
  • 我确实有那把钥匙。我的印象是,将键设置为类型会使其默认应用于所有 DataGridCells。我会在没有钥匙的情况下试一试。
【解决方案3】:

那是因为从来没有产生过错误!!当您分配给ColorWheelCount 而不是_color_wheelCount 时,将添加错误。您永远不会为这些属性分配任何东西。

将您的构造函数更改为:

public Car(int numWheels, string color)
{
    Color = color;
    WheelCount = numWheels;
}

如果您甚至没有看到最初的绿色,那么我能想到的唯一原因是您的 App.xaml 文件的构建操作。确保它是ApplicationDefinition

【讨论】:

  • 通过用户界面将事物分配给这些属性;它们绑定到可编辑的数据网格。
猜你喜欢
  • 2014-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-13
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
相关资源
最近更新 更多