3

没有关于该主题的问题可能表明这里有代码异味,但是......是否可以为类编写扩展方法并将数据绑定到该类,就像您对属性一样?

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

简化的基类:

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();
    }
}

为了进一步增加复杂性,我收到了这些东西的列表,并且我正在尝试绑定到数据网格(XAML 经验非常有限)。

<GroupBox Header="Here is an amazing list of results for you to violate horribly.">
    <DataGrid ItemsSource="{Binding Transmissions, Mode=OneWay}" AutoGenerateColumns="False">
         <DataGrid.Columns>
            <DataGridTextColumn Width="*" Header="Local ID" Binding="{Binding ID, Mode=OneWay}"/>
            <DataGridTextColumn Width="*" Header="Status" Binding="{Binding Status, Mode=OneWay}"/>
         </DataGrid.Columns>
    </DataGrid>
</GroupBox>

我已经测试了代码并且能够毫无困难地绑定到 ID。然而,“状态”根本没有被提及。绑定到扩展属性有技巧吗?或者只编写一个装饰器/外观类并绑定到它会更谨慎吗?

4

2 回答 2

6

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

于 2013-07-18T22:58:16.250 回答
3

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

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。这样做意味着除了属性中的各种更改之外,还绑定了列表。

在这种方法中,您的“扩展”属性只是另一个没有设置器的公开属性。请注意,对影响状态的其他成员的更改代表“扩展”属性调用通知。对传输类的其余成员进行编码大约需要 20 分钟...

于 2013-07-18T23:15:03.353 回答