C# 是否可以将数据绑定到扩展方法?

C# 是否可以将数据绑定到扩展方法?,c#,wpf,data-binding,mvvm,facade,C#,Wpf,Data Binding,Mvvm,Facade,在这个主题上缺乏问题可能是代码气味的一个迹象,但是。。。是否可以像编写属性一样为类编写扩展方法并对其进行数据绑定 假设提供给我的类结构无法从根本上改变,但我想将它的一系列布尔属性表示为字符串,以便于显示 简化基类: public class Transmission { public int ID { get; set; } public bool Cancelled { get; set; } public bool Stored { get; set; } p

在这个主题上缺乏问题可能是代码气味的一个迹象,但是。。。是否可以像编写属性一样为类编写扩展方法并对其进行数据绑定

假设提供给我的类结构无法从根本上改变,但我想将它的一系列布尔属性表示为字符串,以便于显示

简化基类:

public class Transmission
{
    public int ID { get; set; }
    public bool Cancelled { get; set; }
    public bool Stored { get; set; }
    public bool Recorded { get; set; }
}
我的扩展方法:

public static class Extensions
{
    public static string Status(this Transmission trans)
    {
        StringBuilder sb = new StringBuilder("|");
        if (trans.Cancelled)
            sb.Append("| Cancelled ");
        if (trans.Recorded)
            sb.Append("| Recorded ");
        if (trans.Stored)
            sb.Append("| Stored ");
        sb.Append("||");

        return sb.ToString();
    }
}
为了进一步增加复杂性,我收到了这些东西的列表,我正在尝试绑定到datagrid(XAML体验非常有限)



我已经测试了代码,能够毫无困难地绑定到ID。然而,“状态”根本没有被识别。绑定到扩展属性有什么诀窍吗?还是更谨慎的做法是编写一个decorator/facade类并绑定到它?

这就是您通常使用的模式,如MVVM。可以向视图模型添加基于模型且仅与视图相关的特性。视图模型可以包含对模型的引用,以直接绑定到其属性或在视图模型上镜像它们(为了解耦,我选择后者)。

当传递传输对象列表时,您可以使用Façade模式并将它们存储在设计的容器中

public class TransmissionContainer : INotifyPropertyChanged
{
    private readonly Transmission _transmission;
    public TransmissionContainer(Transmission transmission)
    {
        _transmission = transmission;
    }
    private int _id;
    public int Id
    {
        [DebuggerStepThrough]
        get { return _transmission.ID; }
        [DebuggerStepThrough]
        set
        {
            if (value != _transmission.ID)
            {
                _transmission.ID = value;
                OnPropertyChanged("Id");
            }
        }
    }
    public bool Cancelled
    {
        [DebuggerStepThrough]
        get { return _transmission.Cancelled }
        [DebuggerStepThrough]
        set
        {
            if (value != _transmission.Cancelled)
            {
                _transmission.Cancelled = value;
                OnPropertyChanged("Cancelled");
                OnPropertyChanged("Status");
            }
        }
    }
    public string Status
    {
        [DebuggerStepThrough]
        get
        {
            StringBuilder sb = new StringBuilder("|");
            if (_transmission.Cancelled)
                sb.Append("| Cancelled ");
            if (_transmission.Recorded)
                sb.Append("| Recorded ");
            if (_transmission.Stored)
                sb.Append("| Stored ");
            sb.Append("||");
            return sb.ToString();
        }
    }
    //
    // code in other properties here
    //
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}
这是一个容器类,它创建了一个外观,您的Xaml可以透明地绑定到该外观。如图所示,每个公开属性只是回显传输的私有实例中的值。更改通过INotifyPropertyChanged接口中继到WPF绑定引擎

要创建实例,可以使用原始传输类构造它。要绑定这些容器的集合,可以声明TransmissionContainer类型的ObservableCollection。这样做意味着除了属性中的各种更改之外,还将绑定列表


在这种方法中,“extension”属性只是另一个没有setter的公开属性。请注意,对影响状态的其他成员所做的更改将代表“extension”属性调用通知。在Transmission类的其余成员中编码大约需要20分钟…

您无法绑定到扩展方法。。。实际上,你不能绑定到任何方法,必须是一个属性……而且,没有“扩展属性”这样的东西@MarcGravel:不幸的是…@MarcGravel啊,这可能是我的问题。我很困惑,因为我像“Transmission.Status”那样调用扩展,而不是“Transmission.Status()”。需要清楚地阅读扩展。感谢您如此透彻地描述此过程!如果一切顺利的话,我会试一试,并将此标记为答案。考虑到你对问题的描述,它会起作用。您的问题是一个纯粹的外观解决方案,外观模式有着独特的血统这是我第一个使用MVVM的项目,所以这可能是一个愚蠢的问题,但是。。。镜像我收集的对象的最佳方式是什么?是否基于原始传输模型创建新的容器类?这是否与Garry Vass在这个线程上的回答类似?@MadHenchbot:您的集合将包含视图模型(容器类),每个视图模型都包含其模型。这确实与Vass发布的内容类似,他还很好地指出了您需要如何发出更改通知。另外,不要称它们为线程,这是一种侮辱,这是我们没有线程的最强大的一点谢谢你的澄清!
public class TransmissionContainer : INotifyPropertyChanged
{
    private readonly Transmission _transmission;
    public TransmissionContainer(Transmission transmission)
    {
        _transmission = transmission;
    }
    private int _id;
    public int Id
    {
        [DebuggerStepThrough]
        get { return _transmission.ID; }
        [DebuggerStepThrough]
        set
        {
            if (value != _transmission.ID)
            {
                _transmission.ID = value;
                OnPropertyChanged("Id");
            }
        }
    }
    public bool Cancelled
    {
        [DebuggerStepThrough]
        get { return _transmission.Cancelled }
        [DebuggerStepThrough]
        set
        {
            if (value != _transmission.Cancelled)
            {
                _transmission.Cancelled = value;
                OnPropertyChanged("Cancelled");
                OnPropertyChanged("Status");
            }
        }
    }
    public string Status
    {
        [DebuggerStepThrough]
        get
        {
            StringBuilder sb = new StringBuilder("|");
            if (_transmission.Cancelled)
                sb.Append("| Cancelled ");
            if (_transmission.Recorded)
                sb.Append("| Recorded ");
            if (_transmission.Stored)
                sb.Append("| Stored ");
            sb.Append("||");
            return sb.ToString();
        }
    }
    //
    // code in other properties here
    //
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}