我们都喜欢与WPF绑定是多么容易。现在我回来使用Winforms,我正在寻找一种很好的方法将我的网格绑定到BusinessObject的Checkable列表(我坚持使用BindingList for Winforms)。所以我基本上只是在我的业务对象中添加一个可检查项。
我正在使用网格,因为用户将编辑多个列(在此方案中,业务对象上的名称和描述) - 以及向网格添加新对象并从中删除。选中列表框不适合此目的,因为我想编辑列。
为此,我使用的是.NET 4。
我基本上希望减少场景中的UI代码量,因此我使用基于视图模型的方法来填充列表。我希望用户能够检查每个业务对象属性旁边的框。
当然我可以使用继承,但是如果我想对很多业务对象应用相同的机制(有很多不同的屏幕,你可以在列表中检查不同业务对象的项目)。也许这是要走的路 - 但我有疑虑。
现在取决于网格的选择 - 我使用的是Infragistics - 这个功能在概念上非常相似。
我考虑过将业务对象包装在Checkable泛型类中:
using System;
using System.Collections.Generic;
public class Checkable<T> : ModelBase
{
public Checkable(T value)
{
_value = value;
}
private T _value;
public T Value
{
get
{
return _value;
}
set
{
if (!EqualityComparer<T>.Default.Equals(_value, value))
{
_value = value;
OnPropertyChanged("Value");
}
}
}
private bool _checked;
public bool Checked
{
get { return _checked; }
set
{
if (_checked != value)
{
_checked = value;
OnPropertyChanged("Checked");
}
}
}
}
我为这个场景编了一个业务对象:
public class BusinessObject : ModelBase
{
public BusinessObject()
{
}
public BusinessObject(RepairType repairType)
{
_name = repairType.Name;
_id = repairType.Id;
}
private string _name;
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged("Name");
}
}
}
private string _description;
public string Description
{
get { return _description; }
set
{
if (description != value)
{
description = value;
OnPropertyChanged("Description");
}
}
}
private int _id;
public int Id
{
get { return _id; }
set
{
if (_id != value)
{
_id = value;
OnPropertyChanged("Id");
}
}
}
}
ModelBase只实现了INotifyPropertyChanged:
public abstract class ModelBase : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T field, T value, string propertyName = null)
{
if (object.Equals(field, value)) { return false; }
field = value;
OnPropertyChanged(propertyName);
return true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (disposing)
{
PropertyChanged = null;
}
}
}
因此我可能会为我的网格数据源定义:
// in view model
var datasource = new BindingList<Checkable<BusinessObject>>();
... populate list
grid.DataSource = viewmodel.DataSource;
当然,我的场景在某一刻失败,因为Value是具有我想要绑定的属性的BusinessObject引用,而Checked是我也想要绑定到的复选框的属性。
我试图用一些想法启动旧的灰质问题。我不喜欢编写代码来定义网格列。但是,Infragistics网格在设计时可以直接将数据绑定到BusinessObject。可以添加一个未绑定的列(我的方案的复选框)并手动处理项目的检查/取消检查(我可能不得不这样做)。
我想知道我是否遗漏了Winform绑定的任何巧妙的技巧,这些技巧最近在多年前出现时错过了Linq和Entity Framework。