可观察集合在 Winforms 和可能的替代方案中
Winforms .net 3.5 应用程序。在我的应用程序中,我有一个如下所示的通用类:
public class FilterItem {
public FilterItem() { }
public string FilterProperty { get; set; }
public bool FilterPropertyChecked { get; set; }
public ComparitiveOperator FilterOperator { get; set; }
public string FilterValue { get; set; }
}
当我想实现某种过滤功能时,我在所有对话框中使用它。因此,我使用构造函数中传递的预先填充的 List
来调用对话框表单。现在,当对话框加载时,它会遍历每个列表项并添加:
- 复选框
- 组合框
- 文本框
到 TableLayoutPanel 中的每一行。复选框从 FilterProperty
获取其文本属性,从 FilterPropertyChecked
获取其选中状态...组合框从 FilterOperator
获取其绑定...并且文本框从FilterValue
获取其文本值。
请注意我只是说得到。我想做的是当控件的属性必须更改时自动更新这些属性。我听说过 ObservableCollection
,但在添加 System.Collections.ObjectModel
命名空间后,我似乎无法在 Winforms 中“访问”它。
实现这一目标的最佳方法是什么? BindingList 与 INotifyPropertyChanged?我不是后者的专家,并且非常感谢一些指示 - 如果这是我应该走的路。
感谢你!
编辑:
好的,让我发布一些代码来展示我认为我应该做什么:)。我知道我需要在 FilterItem 类上实现 INotifyPropertyChanged ,因此(仅以 FilterValue 部分为例):
public class FilterItem : INotifyPropertyChanged {
public FilterItem() { }
public string FilterProperty { get; set; }
public bool FilterPropertyChecked { get; set; }
public ComparitiveOperator FilterOperator { get; set; }
private string _FilterValue;
public string FilterValue {
get { return this._FilterValue; }
set {
if (this._FilterValue != value) {
this._FilterValue = value;
this.OnFilterValueChanged();
}
}
}
#region INotifyPropertyChanged Members
protected void OnFilterValueChanged() {
var handler = this.PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs("FilterValue"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
现在它应该全部集中在我的 Form_Load 中(这只是对于文本框部分,我省略了 Checkbox 和 ComboBox),如下所示:
private List<FilterItem> FilterList; // <-- this gets assigned to in the constructor
private void dlgFilterData_Load(object sender, EventArgs e) {
foreach (FilterItem item in FilterList) {
txt = new TextBox();
txt.DataBindings.Add("Text", item, "FilterValue", false, DataSourceUpdateMode.OnPropertyChanged);
txt.Dock = DockStyle.Fill;
}
}
文本框的数据绑定数据源是 FilterItem 'item'。但现在我的 Visual Studio IDE 似乎有问题,所以无法尝试这个,但当我启动并运行它时就会。我现在想知道的是:此设置能否成功帮助我的个人 FilterItem
在分配的 Control 各自的属性发生更改时自动更新?
Winforms .net 3.5 app. In my app I have a generic class that looks like so:
public class FilterItem {
public FilterItem() { }
public string FilterProperty { get; set; }
public bool FilterPropertyChecked { get; set; }
public ComparitiveOperator FilterOperator { get; set; }
public string FilterValue { get; set; }
}
and I use it in all of my dialog boxes when I want to implement some sort of filter functionality. So I call the dialog form with a pre-poulated List<FilterItem>
passed in the constructor. Now when the dialog loads, it iterates thru each list-item and adds:
- A checkbox
- A combobox
- A textbox
to every row in a TableLayoutPanel. The Checkbox gets its text property from FilterProperty
and its Checked status from FilterPropertyChecked
...the Combobox gets its binding from FilterOperator
...and the Textbox gets its text value from FilterValue
.
Notice how Im only saying gets. What I would like to do is automatically update these properties when the Controls whose properties they are bound to change. I heard about ObservableCollection<T>
but I dont seem to have 'access' to it in Winforms after adding the System.Collections.ObjectModel
namespace.
What would be the best way to accomplish this. BindingList with INotifyPropertyChanged?? Im not an expert with the latter, and would greatly appreciate some pointers - if this is the way I should be going.
thank u!
EDIT:
Ok, let me post some code to show what I think I should be doing :). I know I need to implement INotifyPropertyChanged
on my FilterItem class, so (just for the FilterValue part for example):
public class FilterItem : INotifyPropertyChanged {
public FilterItem() { }
public string FilterProperty { get; set; }
public bool FilterPropertyChecked { get; set; }
public ComparitiveOperator FilterOperator { get; set; }
private string _FilterValue;
public string FilterValue {
get { return this._FilterValue; }
set {
if (this._FilterValue != value) {
this._FilterValue = value;
this.OnFilterValueChanged();
}
}
}
#region INotifyPropertyChanged Members
protected void OnFilterValueChanged() {
var handler = this.PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs("FilterValue"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
Now it should all come together in my Form_Load (this is just for the Textbox part and I have omitted the Checbox and ComboBox) like so:
private List<FilterItem> FilterList; // <-- this gets assigned to in the constructor
private void dlgFilterData_Load(object sender, EventArgs e) {
foreach (FilterItem item in FilterList) {
txt = new TextBox();
txt.DataBindings.Add("Text", item, "FilterValue", false, DataSourceUpdateMode.OnPropertyChanged);
txt.Dock = DockStyle.Fill;
}
}
the textbox's databindings DataSource is the FilterItem 'item'. But now I seem to be having a problem with my visual studio IDE, so cant try this out, but will when I have it up and running. What I would like to know now is: will this setup successfully assist in allowing my individual FilterItem
s to get automatically updated when their assigned Control's respective property changes??
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
ObservableCollection 类位于 WindowsBase 程序集中,因此您需要将 WindowsBase 添加到项目引用中才能“访问”它。
话虽这么说,我认为 ObservableCollection 不会为您提供您想要的一切。当您添加或删除项目时,您的绑定控件将收到通知,但没有自动属性更改通知,这正是您想要的。
无论您最终使用哪种类型的集合,我认为 INotifyPropertyChanged 都走在正确的道路上。下面是实现 INotifyPropertyChanged 的一个简单示例:
基本上,每当对象的属性发生更改时,都会触发 PropertyChanged 事件,并传递更改的属性的名称。
最后,所有这些可能没有实际意义,因为您说过您想要更改对象属性的值以响应绑定到该属性的控件的更改。通常的 Windows 窗体数据绑定基础结构可以实现这一点,无需 INotifyPropertyChanged 或任何其他接口的帮助。如果您需要通知绑定控件从其他地方对对象属性的更改,则只需实现 INotifyPropertyChanged。
The ObservableCollection class is in the WindowsBase assembly, so you'd need to add WindowsBase to your project references to "access" it.
That being said, I don't think ObservableCollection is going to give you everything you want. Your bound control will get notified when you add or remove items, but there is no automatic property change notification, which is what it sounds like you want.
Regardless of what sort of collection you end up using, I think you're on the right track with INotifyPropertyChanged. Here's a simple example of implementing INotifyPropertyChanged:
Basically, any time a property of your object changes, fire the PropertyChanged event, passing the name of the property that changed.
Finally, all of this may be moot, because you said that you want to change the value of an object's property in response to a change to a control bound to that property. The usual Windows Forms data binding infrastructure can make that happen without the help of INotifyPropertyChanged or any other interface. You only need to implement INotifyPropertyChanged if you need to notify a bound control of changes to your object's properties from elsewhere.