![](/img/trans.png)
[英]How do I use a databound identifier in databound control to get the specific resource in WPF
[英]How do I override the error message on a databound control in WinForms?
我的應用程序中有一個表單,該表單使用綁定源將控件綁定到模型對象。 這樣可以正常工作並處理基本驗證,例如確保用戶沒有在數字字段中輸入文本。 我正在使用ErrorProvider,並設置其datasource =綁定源,以便向用戶顯示錯誤消息,並且效果也不錯。
但是,我在弄清兩件事時遇到了麻煩:
如何以對最終用戶更直觀的方式覆蓋默認錯誤消息。 例如,上述情況下的默認消息是:“輸入字符串的格式不正確”,而我希望它說一些類似的信息:“年齡必須為正整數”。
如何使用更復雜的業務邏輯輕松擴展此系統。 例如,上面的默認處理程序將阻止接受字符串作為數字,但是默認情況下不會強制年齡大於0。 我知道我可以為每個控件覆蓋onValidate,但似乎應該有一個更簡單的方法,它依賴於數據模型,而不是單個控件。
我嘗試按如下方式更新我的設置器,希望該消息隨后顯示在使用此模型對象的所有表單/綁定上,但這不起作用:
Public Property Age() As Integer
Get
Return m_age
End Get
Set(ByVal Value As Integer)
If Not IsNumeric(Value) And Value > 0 Then
Throw New ArgumentException("Age must be a positive integer.")
End If
m_age = Value
End Set
End Property
還有其他想法嗎?
因此,據我所知,這幾乎是可能的,但是由於某些錯誤行為,無法像您希望的那樣簡單。 問題源於格式化程序和類型轉換程序吞噬/覆蓋域對象的錯誤消息這一事實。
這與我所得到的差不多:
對於域對象,您要綁定到:
System.ComponentModel.IDataErrorInfo
,返回所需的用戶友好消息。 INotifyPropertyChanged
以警告更改的綁定源。 將ErrorProvider.DataSource設置為BindingSource。
為要覆蓋默認轉換錯誤消息的每個文本字段的Validating
事件添加一個處理程序。
手動為控件添加綁定,以便您可以關閉格式設置。 如果您不這樣做,那么格式化程序將吃掉您提供的任何自定義錯誤消息。 因此,請勿在VS中使用屬性編輯器。 而是分配綁定ala:
TextBox1.DataBindings.Add("Text", BindingSource1, "Age", False, DataSourceUpdateMode.OnValidation)
如果執行上述操作,則最終用戶將正確看到模型對象的錯誤消息,只要轉換沒有引起錯誤即可。 如果轉換導致錯誤,則他們將看到您在Validating
處理程序中提供的消息(如果有的話),否則將看到常規消息。
仍然不是一個理想的解決方案,但這與我所能達到的接近。 我說不太理想,因為此解決方案無法使用自動格式設置,並且如果您在多個位置使用模型對象,則要求您以不同的形式復制某些驗證消息。
這里。 這應該為您節省大量的工作。
簡而言之:要驗證綁定控件,您需要處理三個事件。
Control.Validating
事件,它在用戶離開控件時驗證數據, Control.Validated
事件,該事件僅在經過正確驗證后才更新數據源,並且 Binding.Parse
事件,當其他任何事情更改控件中的數據(即您的代碼)時,該事件將驗證數據。 為了確保僅將有效數據寫入數據源,在創建Binding
時將關閉對綁定數據的自動更新-這樣, 僅在Control.Validated
事件期間將數據寫入數據源。
Validating
事件和Parse
事件都將驗證錯誤消息放入附加到綁定Control
的ErrorProvider
; 您可能還想通過其他方式顯示錯誤消息,在這種情況下,您需要同時更改這兩個事件。
您可能還需要處理綁定的Format
事件,以控制如何在綁定控件中顯示字段中的數據。
我沒有重寫此代碼以使其通用,因為我不想引入任何錯誤。 因此,我將解釋fc
和cm
是什么,只要您需要知道使其起作用即可。
fc
是包裝我的應用程序的綁定Control
對象的類的實例。 它具有一個Control
屬性(顯然是包裝的控件),然后是Binding
和ErrorProvider
屬性,其用法如下所示。 請注意,由於此代碼為您設置了數據綁定,因此您無需在表單設計器中設置控件的綁定。 嚴格來說,您不需要此類就可以使此代碼正常工作,但是確實可以簡化代碼。 (這里的所有代碼均來自BindingSource
已傳遞到的fc
類上的靜態方法,如圖所示。)
cm
是一個類的實例,該類包含有關將控件綁定到的數據列的元信息,尤其是:
ColumnName
,它在數據源中的名稱(我顯然是綁定到DataColumn
), PropertyName
,它綁定到的控件屬性的名稱(例如"Text"
), NullValue
,如Binding.NullValue
文檔中Binding.NullValue
, Format
,格式化列內部值以在綁定控件中顯示的方法,以及 Parse
,用於將輸入解析為列的內部值的方法。 列的實際驗證邏輯位於此處。 顯然,這是C#,因此您需要弄亂它才能使其在VB中工作,但是區別應該只是語法問題。
// add an ErrorProvider to the control so that we have a place to display
// error messages
fc.ErrorProvider = new ErrorProvider {BlinkStyle = ErrorBlinkStyle.NeverBlink};
// create the Binding. DataSourceUpdateMode.Never bypasses automatic updating
// of the data source; data only gets written to the data source when the
// column is successfully validated.
fc.Binding = fc.Control.DataBindings.Add(
cm.PropertyName,
bindingSource,
cm.ColumnName,
true,
DataSourceUpdateMode.Never,
cm.NullValue);
// this is called whenever the Binding pushes data back to the data source;
// it parses the data in the control into an object that's returned in e.Value.
fc.Binding.Parse += delegate(object sender, ConvertEventArgs e)
{
string property = fc.Binding.PropertyName;
object unparsedValue = fc.Control.GetType().GetProperty(property).GetValue(fc.Control, null);
string message;
// note that we don't actually care about the parsed value if message
// is not null (i.e. if the value is invalid). by convention it's null,
// but it won't ever get written back to the data source.
object parsedValue = cm.Parse(unparsedValue, out message);
if (message != null)
{
fc.ErrorProvider.SetError(fc.Control, message);
}
else
{
fc.ErrorProvider.Clear();
}
e.Value = parsedValue ?? DBNull.Value;
};
// this is called whenever the user leaves the Control.
fc.Control.Validating += delegate
{
string property = fc.Binding.PropertyName;
object value = fc.Control.GetType().GetProperty(property).GetValue(fc.Control, null);
string message;
cm.Parse(value, out message);
if (message != null)
{
fc.ErrorProvider.SetError(fc.Control, message);
}
else
{
fc.ErrorProvider.Clear();
}
};
// this, combined with the DataSourceUpdateMode of Never, insures that the Control's
// value only gets pushed out to the data source after validation is successful.
fc.Control.Validated += delegate {
fc.Binding.WriteValue();
};
// this is called whenever the Binding pulls data from the data source into
// the bound Control
fc.Binding.Format += delegate(object sender, ConvertEventArgs e)
{
e.Value = cm.Format(e.Value);
};
將錯誤返回給調用方。 然后,捕獲要“覆蓋”的異常類型。 與其顯示該異常消息,不如拋出一個自定義異常並顯示其消息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.