【问题标题】:C# Implement interface through delegateC#通过委托实现接口
【发布时间】:2016-07-22 09:39:02
【问题描述】:

我想创建一个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&lt;T&gt;,即使使用起来有点不方便,这也可以解决,但对于INotifyCollectionChanged 的属性则不行,因为这违背了目的 - 如果接口不是由 WPF 实现的,WPF 不会注意到任何更改我绑定到的对象。

那么有没有其他方法可以获得一个类,它的行为类似于ObservableCollection&lt;T&gt;,但也允许我访问像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 属性包含一个 DataSource,它以 DataFieldList 提供行。

【问题讨论】:

    标签: c# interface delegates


    【解决方案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# 不支持多重继承。

    【讨论】:

    • 但是这样,绑定不会尝试使用动态属性...我真的需要一个 WPF 可以用来绑定并接收 CollectionChanged 的​​对象
    • 您能否举例说明您希望如何在 xaml 标记中看到这一点?
    • 我重写了我的代码。看看这个解决方案是否适合你。
    • 所以归根结底是实现所有内容并将其传递给...无论如何,谢谢。如果在接下来的几天内没有发布更好的答案,我会接受这个
    • 任何更改集合的方法,您都可以更改并确保通知他们集合的更改。例如: public void Add(DataField item) { _innerCollection.Add(item); this.PropertyChanged(this, new PropertyChangedEventArgs(item.Name)); } 然后一切都正常了。
    猜你喜欢
    • 2010-11-19
    • 2019-08-05
    • 2020-11-10
    • 2011-05-03
    • 2012-07-05
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多