问题描述
为什么不结束这个问题?
请不要回答这个问题:suggested link不包含答案,因为Binding
中没有DataGridTemplateColumn
属性,而且我找不到绑定的方法数据。
似乎可以在数据模板中使用Text={Binding}
,这是答案的“一半”
原始问题
我是WPF中的新手。
我有一个DataGrid
,我想为某些列使用特定的模板,但是所有模板都是相同的。
例如
<DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<!-- first column is a standard column,ok-->
<DataGridTextColumn Header="First Column" Binding="{Binding FirstColumn}"/>
<!-- a few of the other columns use a custom template-->
<DataGridTemplateColumn Header="Second Column">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding SecondColumn,UpdateSourceTrigger=PropertyChanged}"/
<OtherThings />
<OtherThings />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<More Columns Exactly like the above,with different bindings/>
<!-- Column3 Binding={Binding Column3}-->
<!-- Column4 Binding={Binding Column4}-->
</DataGrid.Columns>
</DataGrid>
如何通过设置模板绑定的方式将模板创建为静态资源?
我试图创建一个静态资源,例如
<DataTemplate x:Key="ColumnTemplate">
<TextBox Text={I have no idea what to put here}/>
<OtherThings/>
<OtherThings/>
<DataTemplate>
并像使用它
<DataGrid>
<DataGrid.Columns>
<!-- Where does the Header go?,where does the binding go?-->
<!-- binds to column 2-->
<DataGridTemplateColumn CellTemplate="{StaticResource ColumnTemplate}">
<!-- binds to column 3-->
<DataGridTemplateColumn CellTemplate="{StaticResource ColumnTemplate}">
</DataGrid.Columns>
</DataGrid>
但是我真的不知道如何正确地从项目到模板内的文本框进行绑定。
我该如何实现?
解决方法
原则上,您可以这样做。 不过,这是否是一个好的计划还是有争议的。
您可以将单元格模板更改为包围与其他标记绑定的任何列。似乎正是您想要的。
对此有一些附属要求,如果您允许在数据网格中进行编辑,则数据网格会将单元格的内容从文本块切换到文本框。除了琐碎的要求外,这是不建议的-但这可能是一个不同的主题。
在数据网格或父资源中:
<Window.Resources>
<Style x:Key="StringStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<StackPanel>
<ContentControl>
<ContentPresenter/>
</ContentControl>
<TextBlock Text="A constant string"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
然后可以将其应用于列:
<DataGridTextColumn Header="Date" Binding="{Binding DT,StringFormat=\{0:dd:hh:mm:ss.FF\}}"
CellStyle="{StaticResource StringStyle}"
如上所述。 单击单元格进行编辑时,可能会发生奇怪的事情。 您可能还希望代码专注于contentpresenter中的文本框。
如果您想减少重复的代码,则可以使用xamlreader使用模板来动态构建列。
如果您只有3列是相同的,那么这可能有点过头,但主要是复制粘贴。
我构建了一个示例来说明这一点:
https://gallery.technet.microsoft.com/WPF-Dynamic-XAML-Awkward-41b0689f
该示例构建了一个移动的月份数据选择。
相关代码在主窗口中
private void Button_Click(object sender,RoutedEventArgs e)
{
// Get the datagrid shell
XElement xdg = GetXElement(@"pack://application:,/dg.txt");
XElement cols = xdg.Descendants().First(); // Column list
// Get the column template
XElement col = GetXElement(@"pack://application:,/col.txt");
DateTime mnth = DateTime.Now.AddMonths(-6);
for (int i = 0; i < 6; i++)
{
DateTime dat = mnth.AddMonths(i);
XElement el = new XElement(col);
// Month in mmm format in header
var mnthEl = el.Descendants("TextBlock")
.Single(x => x.Attribute("Text").Value.ToString() == "xxMMMxx");
mnthEl.SetAttributeValue("Text",dat.ToString("MMM"));
string monthNo = dat.AddMonths(-1).Month.ToString();
// Month as index for the product
var prodEl = el.Descendants("TextBlock")
.Single(x => x.Attribute("Text").Value == "{Binding MonthTotals[xxNumxx].Products}");
prodEl.SetAttributeValue("Text","{Binding MonthTotals[" + monthNo + "].Products}");
// Month as index for the total
var prodTot = el.Descendants("TextBlock")
.Single(x => x.Attribute("Text").Value == "{Binding MonthTotals[xxNumxx].Total}");
prodTot.SetAttributeValue("Text","{Binding MonthTotals[" + monthNo + "].Total}");
cols.Add(el);
}
string dgString = xdg.ToString();
ParserContext context = new ParserContext();
context.XmlnsDictionary.Add("","http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x","http://schemas.microsoft.com/winfx/2006/xaml");
DataGrid dg = (DataGrid)XamlReader.Parse(dgString,context);
Root.Children.Add(dg);
}
private XElement GetXElement(string uri)
{
XDocument xmlDoc = new XDocument();
var xmltxt = Application.GetContentStream(new Uri(uri));
string elfull = new StreamReader(xmltxt.Stream).ReadToEnd();
xmlDoc = XDocument.Parse(elfull);
return xmlDoc.Root;
}
col.txt文件包含列的所有“标准”标记。然后将其作为xml进行操作以替换值。
然后使用xamlreader.parse将结果转换为wpf ui对象
再来一次。
为需求而设计的方法可能只有几列。