wpf Datagrid DataGridTemplateColumn TextBlock 中的二级 属性 绑定

Second-level property binding in wpf Datagrid DataGridTemplateColumn TextBlock

我有一个数据网格,其中的列是在 DataGridTemplateColumn 技术的帮助下创建的。 这是我对 DataGrid (Name = "Dgrv)

感兴趣的列

XAML


<DataGridTemplateColumn Width="40">
                    <!--="Name"-->
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="{Binding TextCell.txtbx}" 
                                           TextAlignment="Center" Margin="0, 8, 0, 0"/>
                                <Canvas Background="Black" Height="1" Margin="5,5,5,0"/>
                                <TextBlock Text="{Binding OperatorCode}" TextAlignment="Center" Margin="0, 5, 0, 0"/>
                            </StackPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

在我的后端我得到了下一个代码:


XAML.cs


var list = new List<Contract>();
        list.Add(new Contract
        {
            ID = 1,
            CompanyName = "Технабсервис",
            HeadName = "Петров\nАлександр\nНиколаевич",
            CountryCode = "+7",
            OperatorCode = "495",
            Date = Convert.ToDateTime("21.02.2012").ToString("dd.MM"), //GetDateTimeFormats('mm, dd'), 
            Time = "16:39",
            Telephones = "(495)123-4567 (общий)",
            Comment = ""
        });
Dgrv.ItemsSource = list;

这是我的classContract.cs


public class Contract
    {
        public int ID { get; set; }
        public string CompanyName { get; set; }
        public string HeadName { get; set; }
        public string CountryCode { get; set; }
        public string OperatorCode { get; set; }
        public String Date { get; set; }
        public String Time { get; set; }
        public String Telephones { get; set; }
        public String Comment { get; set; }
        public TextCell smth { get; set; }

        /*public Dictionary<string, int> PriceFields { get; private set; }
        public Dictionary<string, string> RateFields { get; private set; }
        public Dictionary<string, string> TypeFields { get; private set; }
        public Dictionary<string, string> TicketFields { get; private set; }*/

        public Contract()
        {
            smth = new TextCell();
        }
    }

最后是我的 class TextCell(如您所见,我想将 TextBlock 的文本绑定到此 class 的字段,名称为 "txtbx"


TextCell.cs


public class TextCell
    {
        public String txtbx { get; set; }
        public TextCell()
        {
            txtbx = "sdbjshfk";
        }

        public override string ToString()
        {
            return txtbx;
        }
    }

所以,问题是关于这部分代码

<TextBlock Text="{Binding TextCell.txtbx}" 
                                               TextAlignment="Center" Margin="0, 8, 0, 0"/>

它根本不起作用。我知道,我可以将 TextBlock 的文本绑定到 TextCell 字段本身。在这种情况下将调用 ToString() 方法,但这对我来说还不够。主要是因为 post 中描述的情况只是一个示例,我遇到了更多需要此类绑定的情况。

因此,创建 TextCell class 只是为了理解所需技术的示例。

答案很简单。

如果您想绑定到子属性,您必须使用 Binding 标记扩展中的属性名称。

当你写{Binding TextCell.txtbx}的时候,当然是行不通的,因为你在Contract上没有一个叫TextCell的属性。您有一个名为 smthTextCell 类型的 属性。与 C# 代码类似,您将尝试使用以下代码达到 属性:

var list = new List();
list.Add(new Contract
{
    ID = 1,
    CompanyName = "Технабсервис",
    HeadName = "Петров\nАлександр\nНиколаевич",
    CountryCode = "+7",
    OperatorCode = "495",
    Date = Convert.ToDateTime("21.02.2012").ToString("dd.MM"), //GetDateTimeFormats('mm, dd'), 
    Time = "16:39",
    Telephones = "(495)123-4567 (общий)",
    Comment = ""
});

var x = list[0].smth.txtbx;

顺便说一句,您应该与您的命名约定保持一致。您应该为 public 属性使用 Pascal casing

您可以阅读有关 Binding 标记扩展语法的更多信息 here

您的代码仍有一些问题。如果您从代码更新字段,它不会更新 UI。为了使 list[0].smth.txtbx = "Updated Text"; 工作,您应该在 ContractTextCell class 上实现 INotifyPropertyChanged 接口。沿着这些线的东西:

public class Contract : INotifyPropertyChanged
{
    private int _id;
    private string _companyName;
    private string _headName;
    private string _countryCode;
    private string _operatorCode;
    private string _date;
    private string _time;
    private string _telephones;
    private string _comment;
    private TextCell _smth;

    public int ID
    {
        get { return _id; }
        set
        {
            _id = value;
            OnPropertyChanged();
        }
    }

    public string CompanyName
    {
        get { return _companyName; }
        set
        {
            _companyName = value;
            OnPropertyChanged();
        }
    }

    public string HeadName
    {
        get { return _headName; }
        set
        {
            _headName = value;
            OnPropertyChanged();
        }
    }

    public string CountryCode
    {
        get { return _countryCode; }
        set
        {
            _countryCode = value;
            OnPropertyChanged();
        }
    }

    public string OperatorCode
    {
        get { return _operatorCode; }
        set
        {
            _operatorCode = value;
            OnPropertyChanged();
        }
    }

    public String Date
    {
        get { return _date; }
        set
        {
            _date = value;
            OnPropertyChanged();
        }
    }

    public String Time
    {
        get { return _time; }
        set
        {
            _time = value;
            OnPropertyChanged();
        }
    }

    public String Telephones
    {
        get { return _telephones; }
        set
        {
            _telephones = value;
            OnPropertyChanged();
        }
    }

    public String Comment
    {
        get { return _comment; }
        set
        {
            _comment = value;
            OnPropertyChanged();
        }
    }

    public TextCell smth
    {
        get { return _smth; }
        set
        {
            _smth = value;
            OnPropertyChanged();
        }
    }

    /*public Dictionary<string, int> PriceFields { get; private set; }
    public Dictionary<string, string> RateFields { get; private set; }
    public Dictionary<string, string> TypeFields { get; private set; }
    public Dictionary<string, string> TicketFields { get; private set; }*/

    public Contract()
    {
        smth = new TextCell();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

而对于 TextCell class:

public class TextCell : INotifyPropertyChanged
{
    private string _txtbx;

    public String txtbx
    {
        get { return _txtbx; }
        set
        {
            _txtbx = value;
            OnPropertyChanged();
        }
    }

    public TextCell()
    {
        txtbx = "sdbjshfk";
    }

    public override string ToString()
    {
        return txtbx;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

我知道这是很多样板代码,但不幸的是,如果您希望您的绑定收到有关来自 viewmodel/model 的更改的通知,则需要此代码。 有一个名为 PropertyChanged for Fody 的非常好的库,它可以让您避免为 INotifyPropertyChanged 实现编写所有这些样板代码。但是我有点走神了。

我希望这个 was/will 有用。