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
的属性。您有一个名为 smth
的 TextCell
类型的 属性。与 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";
工作,您应该在 Contract
和 TextCell
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 有用。
我有一个数据网格,其中的列是在 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
的属性。您有一个名为 smth
的 TextCell
类型的 属性。与 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";
工作,您应该在 Contract
和 TextCell
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 有用。