【问题标题】:ErrorProvider - Change BackColor Instead of Showing IconErrorProvider - 更改背景颜色而不是显示图标
【发布时间】:2016-03-12 16:34:04
【问题描述】:

我遇到了一些想要升级的遗留代码。我想更改ErrorProvider 在控件上显示错误状态的方式。默认行为是图标,如果您将鼠标悬停在图标上,则为 ToolTip

我想将此行为更改为更类似于我们在 WPF 控件中使用的行为。这是一个红色的背景色(鲑鱼粉)和控件本身的工具提示。

任何提示、链接或一些前进的方式

编辑。 请参阅下面的答案,了解我的最终结果。

【问题讨论】:

  • 感谢您的反馈。代码现在作为答案发布。再次感谢@Reza-Aghaei

标签: c# winforms idataerrorinfo errorprovider


【解决方案1】:

ErrorProvider 组件不支持此功能,如果您需要,您可以自己创建。

您可以订阅BindingManagerBaseBindingComplete 事件,然后您可以使用包含一些有用属性的BindingCompleteEventArgs 类型的事件arg:

  • ErrorText判断数据绑定是否有错误
  • Binding.Control 确定绑定到的控件

这些足以让我们实施我们的解决方案。

代码

这是一个示例代码,它显示了如何处理BindingComplete 事件并使用它来更改BackColor 和基于控件的有效或无效状态的工具提示。

假设您有一个绑定源myBindingSource,它绑定到实现IDataErrorInfoSampleModel 类。您可以订阅this.BindingContext[this.myBindingSource]BindingComplete事件:

private void Form1_Load(object sender, EventArgs e)
{
    this.myBindingSource.DataSource = new SampleModel();

    var bindingManager = this.BindingContext[this.myBindingSource];
    bindingManager.BindingComplete += bindingManager_BindingComplete;
}

Dictionary<Control, Color> Items = new Dictionary<Control, Color>();
private void bindingManager_BindingComplete(object sender, BindingCompleteEventArgs e)
{
    var control = e.Binding.Control;
    //Store Original BackColor
    if (!Items.ContainsKey(control))
        Items[control] = control.BackColor;

    //Check If there is an error
    if (!string.IsNullOrEmpty(e.ErrorText))
    {
        control.BackColor = Color.Salmon;
        this.errorToolTip.SetToolTip(control, e.ErrorText);
    }
    else
    {
        e.Binding.Control.BackColor = Items[e.Binding.Control];
        this.errorToolTip.SetToolTip(control, null);
    }
}

【讨论】:

    【解决方案2】:

    谢谢礼萨·阿盖伊。这是我根据您的评论和一些额外的搜索得出的...其中一些代码来自msdn resource

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Drawing;
    using System.Linq;
    using System.Security.Permissions;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace ErrorProvider
    {
        class BackgroundColorErrorProvider: Component, IExtenderProvider, ISupportInitialize
        {
    
            public BackgroundColorErrorProvider()
            {
                currentChanged = new EventHandler(ErrorManager_CurrentChanged);
            }
            public BackgroundColorErrorProvider(ContainerControl parentControl)
                : this()
            {
                this.parentControl = parentControl;
                propChangedEvent = new EventHandler(ParentControl_BindingContextChanged);
                parentControl.BindingContextChanged += propChangedEvent;
            }
            public BackgroundColorErrorProvider(IContainer container)
                : this()
            {
                if (container == null) {
                    throw new ArgumentNullException("container");
                }
    
                container.Add(this);
            }
    
            public bool CanExtend(object extendee)
            {
                return extendee is Control && !(extendee is Form) && !(extendee is ToolBar);
            }
    
            private bool inSetErrorManager = false;
            private object dataSource;
            private string dataMember = null;
            private ContainerControl parentControl;
            private BindingManagerBase errorManager;
            private bool initializing;
            private EventHandler currentChanged;
            private EventHandler propChangedEvent;
            private Dictionary<Control, Color> originalColor = new Dictionary<Control, Color>();
            private Color errorBackgroundColor;
    
            public ContainerControl ContainerControl
            {
                [UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
                [UIPermission(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
                get
                {
                    return parentControl;
                }
                set
                {
                    if (parentControl != value)
                    {
                        if (parentControl != null)
                            parentControl.BindingContextChanged -= propChangedEvent;
    
                        parentControl = value;
    
                        if (parentControl != null)
                            parentControl.BindingContextChanged += propChangedEvent;
    
                        Set_ErrorManager(this.DataSource, this.DataMember, true);
                    }
                }
            }
    
            public string DataMember
            {
                get { return dataMember; }
                set
                {
                    if (value == null) value = "";
                    Set_ErrorManager(this.DataSource, value, false);
                }
            }
    
            public object DataSource
            {
                get { return dataSource; }
                set 
                { 
                    if ( parentControl != null && value != null && String.IsNullOrEmpty(this.dataMember))
                    {
                        // Let's check if the datamember exists in the new data source
                        try
                        {
                            errorManager = parentControl.BindingContext[value, this.dataMember];
                        }
                        catch (ArgumentException)
                        {
                            // The data member doesn't exist in the data source, so set it to null
                            this.dataMember = "";
                        }
                    }
                    Set_ErrorManager(value, this.DataMember, false);
                }
            }
    
            public override ISite Site
            {
                set
                {
                    base.Site = value;
                    if (value == null)
                        return;
    
                    IDesignerHost host = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
                    if (host != null)
                    {
                        IComponent baseComp = host.RootComponent;
    
                        if (baseComp is ContainerControl)
                        {
                            this.ContainerControl = (ContainerControl)baseComp;
                        }
                    }
                }
            }
            private ToolTip toolTip;
    
            public ToolTip ToolTip
            {
                get { return toolTip; }
                set { toolTip = value; }
            }
    
            public Color ErrorBackgroundColor
            {
                get { return errorBackgroundColor; }
                set { errorBackgroundColor = value; }
            }
    
            private void Set_ErrorManager(object newDataSource, string newDataMember, bool force)
            {
                if (inSetErrorManager)
                    return;
                inSetErrorManager = true;
                try
                {
                    bool dataSourceChanged = this.DataSource != newDataSource;
                    bool dataMemberChanged = this.DataMember != newDataMember;
    
                    //if nothing changed, then do not do any work
                    //
                    if (!dataSourceChanged && !dataMemberChanged && !force)
                    {
                        return;
                    }
    
                    // set the dataSource and the dataMember
                    //
                    this.dataSource = newDataSource;
                    this.dataMember = newDataMember;
    
                    if (!initializing)
                    {
                        UnwireEvents(errorManager);
    
                        // get the new errorManager
                        //
                        if (parentControl != null && this.dataSource != null && parentControl.BindingContext != null)
                        {
                            errorManager = parentControl.BindingContext[this.dataSource, this.dataMember];
                        }
                        else
                        {
                            errorManager = null;
                        }
    
                        // wire the events
                        //
                        WireEvents(errorManager);
    
                        // see if there are errors at the current
                        // item in the list, w/o waiting for the position to change
                        if (errorManager != null)
                            UpdateBinding();
                    }
                }
                finally
                { 
                    inSetErrorManager = false;
                }
            }
    
            public void UpdateBinding()
            {
                ErrorManager_CurrentChanged(errorManager, EventArgs.Empty);
            }
    
            private void UnwireEvents(BindingManagerBase listManager)
            {
                if (listManager != null)
                {
                    listManager.CurrentChanged -= currentChanged;
                    listManager.BindingComplete -= new BindingCompleteEventHandler(this.ErrorManager_BindingComplete);
    
                    CurrencyManager currManager = listManager as CurrencyManager;
    
                    if (currManager != null)
                    {
                        currManager.ItemChanged -= new ItemChangedEventHandler(this.ErrorManager_ItemChanged);
                        currManager.Bindings.CollectionChanged -= new CollectionChangeEventHandler(this.ErrorManager_BindingsChanged);
                    }
                }
    
            }
    
            private void WireEvents(BindingManagerBase listManager)
            {
                if (listManager != null)
                {
                    listManager.CurrentChanged += currentChanged;
                    listManager.BindingComplete += new BindingCompleteEventHandler(this.ErrorManager_BindingComplete);
    
                    CurrencyManager currManager = listManager as CurrencyManager;
    
                    if (currManager != null)
                    {
                        currManager.ItemChanged += new ItemChangedEventHandler(this.ErrorManager_ItemChanged);
                        currManager.Bindings.CollectionChanged += new CollectionChangeEventHandler(this.ErrorManager_BindingsChanged);
                    }
                }
            }
    
    
            private void ErrorManager_BindingsChanged(object sender, CollectionChangeEventArgs e)
            {
                ErrorManager_CurrentChanged(errorManager, e);
            }
    
            private void ParentControl_BindingContextChanged(object sender, EventArgs e)
            {
                Set_ErrorManager(this.DataSource, this.DataMember, true);
            }
    
            private void ErrorManager_ItemChanged(object sender, ItemChangedEventArgs e)
            {
                BindingsCollection errBindings = errorManager.Bindings;
                int bindingsCount = errBindings.Count;
    
                // If the list became empty then reset the errors
                if (e.Index == -1 && errorManager.Count == 0)
                {
                    for (int j = 0; j < bindingsCount; j++)
                    {
                        if ((errBindings[j].Control != null))
                        {
                            // ...ignore everything but bindings to Controls
                            SetError(errBindings[j].Control, "");
                        }
                    }
                }
                else
                {
                    ErrorManager_CurrentChanged(sender, e);
                }
            }
    
            private void SetError(Control control, string p)
            {
                if (String.IsNullOrEmpty(p))
                {
                    if (originalColor.ContainsKey(control))
                        control.BackColor = originalColor[control];
                    toolTip.SetToolTip(control, null);
                }
                else
                {
                    control.BackColor = ErrorBackgroundColor;
                    toolTip.SetToolTip(control, p);
                }
            }
    
            private void ErrorManager_BindingComplete(object sender, BindingCompleteEventArgs e)
            {
                Binding binding = e.Binding;
    
                if (binding != null && binding.Control != null)
                {
                    SetError(binding.Control, (e.ErrorText == null ? String.Empty : e.ErrorText));
                }
            }
    
            private void ErrorManager_CurrentChanged(object sender, EventArgs e)
            {
                if (errorManager.Count == 0)
                {
                    return;
                }
    
                object value = errorManager.Current;
                if (!(value is IDataErrorInfo))
                {
                    return;
                }
    
                BindingsCollection errBindings = errorManager.Bindings;
                int bindingsCount = errBindings.Count;
    
                // We can only show one error per control, so we will build up a string...
                //
                Hashtable controlError = new Hashtable(bindingsCount);
    
                for (int j = 0; j < bindingsCount; j++)
                {
    
                    // Ignore everything but bindings to Controls
                    if (errBindings[j].Control == null)
                    {
                        continue;
                    }
    
                    string error = ((IDataErrorInfo)value)[errBindings[j].BindingMemberInfo.BindingField];
    
                    if (error == null)
                    {
                        error = "";
                    }
    
                    string outputError = "";
    
                    if (controlError.Contains(errBindings[j].Control))
                        outputError = (string)controlError[errBindings[j].Control];
    
                    // VSWhidbey 106890: Utilize the error string without including the field name.
                    if (String.IsNullOrEmpty(outputError))
                    {
                        outputError = error;
                    }
                    else
                    {
                        outputError = string.Concat(outputError, "\r\n", error);
                    }
    
                    controlError[errBindings[j].Control] = outputError;
                }
    
                IEnumerator enumerator = controlError.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    DictionaryEntry entry = (DictionaryEntry)enumerator.Current;
                    SetError((Control)entry.Key, (string)entry.Value);
                }
            }
    
    
            public void BeginInit()
            {
                initializing = true;
            }
    
            public void EndInit()
            {
                initializing = false;
                Set_ErrorManager(this.DataSource, this.DataMember, true);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-25
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 2017-03-25
      相关资源
      最近更新 更多