我坚持使用一些我希望升级的遗留代码。我想更改ErrorProvider
在控件上显示错误状态的方式。默认行为是图标,如果您将鼠标悬停在图标上,则为ToolTip
。
我想将此行为更改为与我们在WPF控件中使用的行为更相似。这是一种红色的背色(鲑鱼粉色)和控制本身的工具尖端。
任何提示,链接或某种方式前进
EDIT。 关于我最终得到的结论,请参阅下面的答案。
答案 0 :(得分:1)
ErrorProvider
组件不支持此功能,如果您需要,可以自行创建。
您可以订阅BindingComplete
的{{1}}事件,然后您可以使用包含一些有用属性的BindingManagerBase
类型的事件arg:
BindingCompleteEventArgs
确定数据绑定是否存在错误ErrorText
确定与这些足以让我们实施我们的解决方案。
<强>代码强>
下面是一个示例代码,说明如何处理Binding.Control
事件,并根据事件的有效或无效状态使用它来更改控件的BindingComplete
和工具提示。
假设您有一个绑定源BackColor
,它绑定到myBindingSource
类,该类已实现SampleModel
。您可以订阅IDataErrorInfo
事件BindingComplete
:
this.BindingContext[this.myBindingSource]
答案 1 :(得分:1)
谢谢Reza Aghaei。这是我根据您的评论和其他一些搜索提出的...其中一些代码来自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);
}
}
}