如何在WPF中使用ValidatesOnDataErrors绑定空文本框时阻止UI冻结?

时间:2016-06-27 07:04:04

标签: c# wpf code-behind

@Bijington在评论中回答,请参阅更新2

当我开始将鼠标悬停在绑定到对象属性的空文本框上时,我遇到了一些问题。 我无法再与我的应用程序交互,CPU使用率从大约5%上升到超过50%。只有在我将ValidatesOnDataErrors设置为true并且文本框开始标记为无效(这是故意的)时才会发生这种情况。

以下是一些可能相关的短端代码:

提供数据的对象

public class Product : Item
{
    public string Name
    {
        get
        {
            return row.Field<string>("name");
        }
        set
        {
            row.SetField<string>("name", value);
            OnPropertyChanged("Name");
        }
    }

    public override SelectTables Table
    {
        get
        {
            return classToSelectTables<Product>();
        }
    }

    public override object[] ItemFields
    {
        get
        {
            return row.ItemArray;
        }
        set
        {
            row.ItemArray = value;
            OnPropertyChanged("ItemFields");
            OnPropertyChanged("Name");
        }
    }

    public override string this[string columnName]
    {
        get
        {
            string errorMessage = string.Empty;
            switch (columnName)
            {
                case "Name":
                    if (string.IsNullOrWhiteSpace(Name))
                    {
                        errorMessage = "Der Name muss zwischen " + MinLenght + " und " + MaxLenght + " Zeichen lang sein.";
                    }
                    break;
                default:
                    break;
            }
            Debug.WriteLine("Errorcheck " + errorMessage);
            return errorMessage;
        }
    }

    public Product() : base() { }

    public Product(ref DataRow row) : base(ref row) { }
}

进行绑定的类

class ItemBinding<T> where T : Item
{
    private ItemViewModel<T> viewModel;
    public ItemViewModel<T> ViewModel
    {
        get
        {
            return viewModel;
        }
    }

    private string CurrencyFormat
    {
        get
        {
            return "C";
        }
    }

    public ItemBinding()
    {
        viewModel = (ItemViewModel<T>)getViewModel(Item.classToSelectTables<T>());
    }

    private Binding getBinding(PropertyPath path, string format = null)
    {
        Binding binding = new Binding();
        binding.Path = path;
        binding.Source = viewModel.Temporary;
        binding.ValidatesOnDataErrors = true;
        binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        if (format != null)
        {
            binding.ConverterCulture = CultureInfo.CurrentCulture;
            binding.StringFormat = format;
        }
        return binding;
    }

    public void doDefaultBinding(TextBox text, PropertyPath path)
    {
        BindingOperations.SetBinding(text, TextBox.TextProperty, getBinding(path));
    }
}

更新

这是基类Item

    public abstract class Item : INotifyPropertyChanged, IDataErrorInfo
{
    protected DataRow row;

    public abstract object[] ItemFields { get; set; }


    public long? Id
    {
        get
        {
            return row.Field<long?>("id");
        }
    }

    public abstract SelectTables Table { get; }

    public string Error
    {
        get
        {
            return string.Empty;
        }
    }

    public abstract string this[string columnName]
    {
        get;
    }

    public Item()
    {
        Debug.WriteLine("new " + typeof(Item).ToString());
        if (row != null)
        {
            return;
        }
        row = Tables[(int)Table].NewRow();
    }

    public Item(ref DataRow row) : this()
    {
        this.row = row;
    }

    public DataRow getCopyOfRow()
    {
        DataRow row = Tables[(int)Table].NewRow();
        row.ItemArray = (object[])this.row.ItemArray.Clone();
        return row;
    }

    public static SelectTables classToSelectTables<T>()
    {
        Type t = typeof(T);
        return DatabaseManager.getTable(t.Name);
    }

    public void add()
    {
        Tables[(int)Table].Rows.Add(row);
    }

    public void delete()
    {
        if (row == null)
        {
            return;
        }
        row.Delete();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            Debug.WriteLine("PropertyChanged");
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

更新2 原来我是个白痴。我忘了不在文本框样式中设置工具提示的路径。现在它起作用了:

            <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip" Value="{Binding Path=(Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}"/>
            </Trigger>
        </Style.Triggers>

0 个答案:

没有答案