C# 可绑定只读列表

C# 可绑定只读列表,c#,winforms,C#,Winforms,我有一个包含TicketLine对象集合的Ticket类。我想将此集合绑定到DataGridView,但不允许除票证类之外的任何东西从中添加和删除项 到目前为止,我在TicketLine中使用了BindingList和implementet INotifyPropertyChanged,但这会暴露列表本身的Add和Remove方法 如何将此集合添加到DataGridView,而不公开Ticket类以外的其他添加/删除方法?我可以想到的是,通过将所有调用委托给包装的读/写绑定列表,使用decora

我有一个包含TicketLine对象集合的Ticket类。我想将此集合绑定到DataGridView,但不允许除票证类之外的任何东西从中添加和删除项

到目前为止,我在TicketLine中使用了BindingList和implementet INotifyPropertyChanged,但这会暴露列表本身的Add和Remove方法


如何将此集合添加到DataGridView,而不公开Ticket类以外的其他添加/删除方法?

我可以想到的是,通过将所有调用委托给包装的读/写绑定列表,使用decorator模式实现接口。唯一的例外是:

  • 允许编辑/添加/删除返回false的成员
  • 添加/删除引发InvalidOperationException(或NotSupportedException)的方法 这就是只读方面的保证方式
创建此只读包装后,将其传递给DataGridView。如果它尊重合同(我假设它是:),它应该不允许修改基础列表


有一次,我遇到了同样的问题,解决方案太麻烦,无法实施。主要是因为失去了泛型和所需的工作量。不过,我希望它能有所帮助。

我能想到的是,通过将所有调用委托给包装的读/写绑定列表,使用decorator模式实现接口。唯一的例外是:

  • 允许编辑/添加/删除返回false的成员
  • 添加/删除引发InvalidOperationException(或NotSupportedException)的方法 这就是只读方面的保证方式
创建此只读包装后,将其传递给DataGridView。如果它尊重合同(我假设它是:),它应该不允许修改基础列表


有一次,我遇到了同样的问题,解决方案太麻烦,无法实施。主要是因为失去了泛型和所需的工作量。不过,我希望它能有所帮助。

您可以隐藏列表,只公开IEnumerable属性:

public class Ticket : INotifyPropertyChanged
{
    private List<TicketLine> ticketLines;

    public IEnumerable<TicketLine> TicketLines
    {
        get { return ticketLines.AsReadOnly(); }
    }

    public void Add(TicketLine ticketLine)
    {
        ticketLines.Add(ticketLine);
        OnPropertyChanged("TicketLines");
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
公共类票证:INotifyPropertyChanged
{
私人名单售票线路;
公共数字票务线
{
获取{return ticketLines.AsReadOnly();}
}
公共作废添加(票证行票证行)
{
ticketLine.Add(ticketLine);
不动产变更(“票务线”);
}
公共事件属性更改事件处理程序属性更改;
私有void OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}

您可以隐藏列表并仅公开IEnumerable属性:

public class Ticket : INotifyPropertyChanged
{
    private List<TicketLine> ticketLines;

    public IEnumerable<TicketLine> TicketLines
    {
        get { return ticketLines.AsReadOnly(); }
    }

    public void Add(TicketLine ticketLine)
    {
        ticketLines.Add(ticketLine);
        OnPropertyChanged("TicketLines");
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
公共类票证:INotifyPropertyChanged
{
私人名单售票线路;
公共数字票务线
{
获取{return ticketLines.AsReadOnly();}
}
公共作废添加(票证行票证行)
{
ticketLine.Add(ticketLine);
不动产变更(“票务线”);
}
公共事件属性更改事件处理程序属性更改;
私有void OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}

BindingList提供ListChanged事件,例如网格控件使用该事件。您的解决方案缺少此事件。BindingList提供ListChanged事件,该事件由网格控件等使用。您的解决方案缺少此事件。