在WPF DataGridCell上设置验证错误的样式

时间:2010-09-30 15:12:14

标签: .net wpf validation styles

我正在尝试更改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();
        }
    }

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

以下情况是否失败?不是轮数和颜色

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

HTH

答案 2 :(得分:0)

那是因为没有错误产生!!分配给Color&amp;时会添加错误WheelCount,而非_color&amp; _wheelCount。你永远不会为这些属性分配任何东西。

将构造函数更改为:

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

如果您甚至没有看到初始绿色,那么我能想到的唯一原因就是App.xaml文件的Build Action。确保它是ApplicationDefinition