C#通过委托

时间:2016-07-22 09:39:03

标签: c# interface delegates

我想创建ObservableList<T>,但是作为DynamicObject,我可以将元素映射为属性。这就是为什么我必须继承DynamicObject而不是ObservableList<T>

public class DataFieldList : DynamicObject, ICollection<DataField>, INotifyCollectionChanged
{
    private ObservableList<DataField> _list;

    public DataFieldList()
    {
        _list = new ObservableList<DataField>();
    }

    public Object this[String name]
    {
        get
        {
            return _list.FirstOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase))?.Value;
        }
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = this[binder.Name];
        return result != null;
    }
}

现在我仍然需要实现接口,所以我可以像ObservableCollection一样使用该类。我想使用我的_list作为实现这些接口的委托,但这似乎是不可能的......

此功能通过implements属性关键字包含在Delphi中:

property Collection: ICollection read _list implements ICollection;

我知道thisthis问题基本相同,但继承的解决方案对我来说是不可能的,而且我也不能将接口公开为属性。即使对ICollection<T>使用有点不方便,这也会有用,但对于INotifyCollectionChanged的属性则不行,因为这会破坏目的 - 如果界面不是,WPF将不会注意到任何变化。由我绑定的对象实现。

有没有其他方法可以获得一个类,它的行为类似ObservableCollection<T>,但也允许我访问动态属性,如DynamicObject

用例是一个网格,它将DataFieldList的集合作为源代码以及列名称集合。

<Style BasedOn="{StaticResource {x:Type dxg:GridControl}}" TargetType="{x:Type controls:DataGrid}">
    <Setter Property="ItemsSource" Value="{TemplateBinding Rows}">
    <Setter Property="ColumnsSource" Value="{TemplateBinding Columns}">
    <Setter Property="ColumnGeneratorTemplate">
        <Setter.Value>
            <DataTemplate>
                <ContentControl>
                    <dxg:GridColumn FieldName="{Binding Name}"/>
                </ContentControl>
            </DataTemplate>
        </Setter.Value>
    </Setter>  
</Style>

此处,Rows属性包含一个将行提供为DataFieldList的DataSource。

1 个答案:

答案 0 :(得分:1)

如果我理解正确,你应该得到类似的东西

public class DataField
{
    public string Name { get; set; }

    public object Value { get; set; }
}

public class PropertiesCollection
{
    public PropertiesCollection(IEnumerable<DataField> collection)
    {
        _collection = collection;
    }

    private IEnumerable<DataField> _collection;

    public object this[string name]
    {
        get
        {
            return _collection.FirstOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase))?.Value;
        }
    }
}

public class CustomList : ObservableCollection<DataField>
{
    private PropertiesCollection _collection;

    public CustomList()
    {
        _collection = new PropertiesCollection(this);
    }

    public PropertiesCollection Properties
    {
        get
        {
            return _collection;
        }
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        OnPropertyChanged(new PropertyChangedEventArgs(nameof(Properties)));
        base.OnCollectionChanged(e);
    }
}

绑定看起来像这样:

    <TextBlock Text="{Binding Properties[SomeProperty],Mode=OneWay}">            
    </TextBlock>

即我只使用合成而不是继承。 不幸的是,我们必须只对组合感到满意(并且您非常清楚C#中不支持多重继承。