DataGrid研究笔记-2

上次写了焦点控制,这次讲一下,校验和错误提示。

wpf自带有ValidationRule

第一种:写说下ValidationRule的使用情况。

继承ValidationRule, override Validate方法。

然后xaml里

<Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="Validation.HasError" Value="True" />
                        <Condition Property="IsFocused" Value="True" />
                    </MultiTrigger.Conditions>
                    <Setter Property="Validation.ErrorTemplate">
                        <Setter.Value>
                            <ControlTemplate>
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto" />
                                        <RowDefinition />
                                    </Grid.RowDefinitions>
                                    <AdornedElementPlaceholder Name="MyAdorner" />

                                    <Border Grid.Row="1"
                                            Height="20"
                                            Margin="10,-1,0,0"
                                            Background="#FFE2402F"
                                            CornerRadius="4"
                                            Opacity="30">
                                        <Border.Effect>
                                            <DropShadowEffect ShadowDepth="0" />
                                        </Border.Effect>
                                        <TextBlock Margin="8,0"
                                                   FontSize="11"
                                                   VerticalAlignment="Center"
                                                   Foreground="White"
                                                   Text="{Binding ElementName=MyAdorner,
                                                                  Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
                                                   TextWrapping="Wrap" />
                                    </Border>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="Foreground" Value="red" />
                </MultiTrigger>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="Foreground" Value="red" />
                </Trigger>
            </Style.Triggers>


第二种:IDataErrorInfo类,可以在定义的ViewModel里继承,

主要两个方法

public string Error


public string this[string columnName]

xaml使用情况同第一中种。

但是前面几种可以提示错误信息,但是有错误时,无法不让焦点移动。

下面我说说第三种方法:

首先定义接口:

 public interface IContextValidation
    {
        ValidationResult Validate(DependencyObject sender);
    }

 public interface IContextValidationPolicy
    {
        void Run(DependencyObject sender, object content);
    }


然后扩展接口

public abstract class CodeValidationBase : IContextValidation
    {
        public string MethodName { get; set; }
    }

public abstract class CodePolicyBase : IContextValidationPolicy
    {
        public string MethodName { get; set; }
        public abstract void Run(System.Windows.DependencyObject sender, object content);
    }


接下来实现接口

public class ClientCodeValidation : CodeValidationBase
    {
        public override ValidationResult Validate(DependencyObject sender)
        {
            Requires.NotNull(sender, "sender");
            Requires.NotNull(this.MethodName, "MethodName");
            object obj=null;
            return (ValidationResult)sender.SafeInvoke(new Func<ValidationResult>(() =>
            {
                var page = this.GetVisualParent<Window>(sender as Visual);
                if (sender is TextBox)
                {
                    obj = ((TextBox)sender).Text;
                }
                else if (sender is DataGridCell)
                {
                    var temp = (sender as DataGridCell).Content;
                    if (temp is TextBox)
                    {
                        obj = ((TextBox)temp).Text;
                    }
                    else if (temp is TextBlock)
                    {
                        obj = ((TextBlock)temp).Text;
                    }
                }
                else
                {
                    var textBoxBase = this.GetVisualChild<TextBox>(sender as Visual);
                    if (textBoxBase != null)
                    {
                        obj = ((TextBox)textBoxBase).Text;
                    }
                }
                if (page == null)
                {
                    throw new InvalidOperationException("Cannot find page which owns sender");
                }
                return page.ReflectCallInstanceMethod<ValidationResult>(
                    this.MethodName, new Type[] { typeof(object) }, obj);
            }));
        }
}
public class KeepFocusPolicy : IContextValidationPolicy
    {
        public void Run(System.Windows.DependencyObject sender, object content)
        {
            Requires.NotNull(sender, "sender");
            var element = sender as FrameworkElement;
            if (element == null)
            {
                throw new ArgumentException("sender must be FrameworkElement", "sender");
            }
            element.SafeInvoke(() => element.Focus());
        }
    }

public sealed class ShowTipPolicy : IContextValidationPolicy
    {
        public TipAdornerPlacement Placement { get; set; }

        public void Run(System.Windows.DependencyObject sender, object content)
        {
            var element = sender as FrameworkElement;
            if (element == null) return;

            sender.SafeInvoke(() =>
            {
                var message = content == null ? "输入错误" : content.ToString();
                element.ShowTipAdorner(Placement, message);
            });
        }
    }

 

最后我们就可以在焦点移动前,去做判断了:

var myDataGridTextColumn = currentCellContainer.Column as MyDataGridTextColumn;
                if (myDataGridTextColumn != null)
                {
                    var validations = myDataGridTextColumn.Validations;
                    var errorPolicies = myDataGridTextColumn.ErrorPolicies;
                    bool hasError = false;
                    object errMessage = null;
                    validations.ForEach(o =>
                        {
                            var result = o.Validate(focuseElement);
                            if (!result.IsValid)
                            {
                                hasError = true;
                                errMessage = result.ErrorContent;
                            }
                        });
                    if (hasError)
                    {
                        errorPolicies.ForEach(o => o.Run(focuseElement, errMessage));
                        this.SetValue(CurrentCellProperty, new DataGridCellInfo(currentCellContainer));
                        //this.SetValue(MyCurrentCellProperty, currentCellContainer);
                        var temp = this.CurrentCell;
                        //focuseElement.Focus();
                        return;
                    }
                }

 

xmal里使用:

<local:MyDataGridTextColumn Header="BBB" Width="100" Binding="{Binding B}">
                    <local:MyDataGridTextColumn.Validations>
                        <local:ClientCodeValidation MethodName="Validation"/>
                    </local:MyDataGridTextColumn.Validations>
                    <local:MyDataGridTextColumn.ErrorPolicies>
                        <local:ShowTipPolicy Placement="Right" />
                        <local:KeepFocusPolicy />
                    </local:MyDataGridTextColumn.ErrorPolicies>
                </local:MyDataGridTextColumn>

校验事件,写在前台,校验的时候会使用反射,调用。

 public ValidationResult Validation(object value)
        {
            if ((string)value == "5")
            {
                return new ValidationResult(false, "不能为5");
            }
            return new ValidationResult(true, string.Empty);
        }

 

 

posted @ 2013-09-06 15:02  gavin.huang  阅读(259)  评论(0编辑  收藏  举报