带有 valueconverter 的动态数据模板
我想在 wpftoolkit 数据网格中显示数据,其中数据是
public class Thing
{
public string Foo { get; set; }
public string Bar { get; set; }
public List<Candidate> Candidates { get; set; }
}
public class Candidate
{
public string Name { get; set; }
public CandidateType CandidateType { get; set; }
}
public enum CandidateType
{
Type1,
Type2,
Type42
}
候选列表中候选数量可在运行时配置的集合。
所需的网格布局如下
所示 酒吧| 候选人 1 | 候选人2 | ... | Candidate N
因此,我似乎无法在 xaml 中为候选者创建 DataTemplate,因为绑定表达式将会改变。
我在 AutoGenerateColumns 事件中添加必要的列,如下所示:
private void DataGrid_AutoGeneratedColumns(object sender, EventArgs e)
{
ViewModel vm = DataContext as ViewModel;
for (int i = 0; i < vm.LotsOfThings.First().Candidates.Count; i++)
{
string assName = Assembly.GetExecutingAssembly().GetName().Name;
ParserContext ctx = new ParserContext();
ctx.XamlTypeMapper = new XamlTypeMapper(new string[] { assName });
ctx.XamlTypeMapper.AddMappingProcessingInstruction("src", "WpfToolkitDataGridTester", assName);
ctx.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
ctx.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
ctx.XmlnsDictionary.Add("src", "clr-namespace:WpfToolkitDataGridTester;assembly=" + assName);
var template = XamlReader.Parse(@"<DataTemplate>
<DataTemplate.Resources>
<src:FooConverter x:Key='fooConverter' />
</DataTemplate.Resources>
<TextBlock
Foreground='{Binding Candidates[" + i + @"].CandidateType,Converter={StaticResource fooConverter}}'
Text='{Binding Candidates[" + i + @"].Name}' />
</DataTemplate>", ctx) as DataTemplate;
dg.Columns.Add(new DataGridTemplateColumn
{
Header = "Candidate " + (i + 1),
CellTemplate = template
});
}
}
但是,这会失败,但出现以下异常: XML 命名空间“clr-namespace:WpfToolkitDataGridTester; assembly=WpfToolkitDataGridTester”中不存在标记“FooConverter”。 第“3”行位置“54”。
将 StaticResource 更改为 DynamicResource 不会发生任何变化。
我缺少什么?
FWIW:硬编码的数据模板
<DataTemplate x:Key="candidateTemplate">
<DataTemplate.Resources>
<src:FooConverter x:Key="fooConverter" />
</DataTemplate.Resources>
<TextBlock
Foreground="{Binding Candidates[0].CandidateType,Converter={StaticResource fooConverter}}"
Text="{Binding Candidates[0].Name}" />
</DataTemplate>
和模板列定义如下
<wpftk:DataGridTemplateColumn CellTemplate="{StaticResource candidateTemplate}" />
“有效”,但显然不会产生所需的结果,因为 Candidates[0] 是硬编码的。
I want to show data in a wpftoolkit datagrid where the data is a collection of
public class Thing
{
public string Foo { get; set; }
public string Bar { get; set; }
public List<Candidate> Candidates { get; set; }
}
public class Candidate
{
public string Name { get; set; }
public CandidateType CandidateType { get; set; }
}
public enum CandidateType
{
Type1,
Type2,
Type42
}
where the number of candidates in Candidates list is configurable at runtime.
Desired grid layout looks like this
Foo | Bar | Candidate 1 | Candidate 2 | ... | Candidate N
Thus it seems I cannot create a DataTemplate for the candidates in xaml as the binding expression will change.
I add necessary columns in AutoGeneratedColumns event like so:
private void DataGrid_AutoGeneratedColumns(object sender, EventArgs e)
{
ViewModel vm = DataContext as ViewModel;
for (int i = 0; i < vm.LotsOfThings.First().Candidates.Count; i++)
{
string assName = Assembly.GetExecutingAssembly().GetName().Name;
ParserContext ctx = new ParserContext();
ctx.XamlTypeMapper = new XamlTypeMapper(new string[] { assName });
ctx.XamlTypeMapper.AddMappingProcessingInstruction("src", "WpfToolkitDataGridTester", assName);
ctx.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
ctx.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
ctx.XmlnsDictionary.Add("src", "clr-namespace:WpfToolkitDataGridTester;assembly=" + assName);
var template = XamlReader.Parse(@"<DataTemplate>
<DataTemplate.Resources>
<src:FooConverter x:Key='fooConverter' />
</DataTemplate.Resources>
<TextBlock
Foreground='{Binding Candidates[" + i + @"].CandidateType,Converter={StaticResource fooConverter}}'
Text='{Binding Candidates[" + i + @"].Name}' />
</DataTemplate>", ctx) as DataTemplate;
dg.Columns.Add(new DataGridTemplateColumn
{
Header = "Candidate " + (i + 1),
CellTemplate = template
});
}
}
This however fails with the following exception:
The tag 'FooConverter' does not exist in XML namespace 'clr-namespace:WpfToolkitDataGridTester;assembly=WpfToolkitDataGridTester'. Line '3' Position '54'.
Changing the StaticResource to DynamicResource makes no change.
What am I missing?
FWIW: a hardcoded datatemplate
<DataTemplate x:Key="candidateTemplate">
<DataTemplate.Resources>
<src:FooConverter x:Key="fooConverter" />
</DataTemplate.Resources>
<TextBlock
Foreground="{Binding Candidates[0].CandidateType,Converter={StaticResource fooConverter}}"
Text="{Binding Candidates[0].Name}" />
</DataTemplate>
and the template column defined like so
<wpftk:DataGridTemplateColumn CellTemplate="{StaticResource candidateTemplate}" />
'works' but obviously does not produce the desired result as Candidates[0] is hardcoded.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
无论出于何种原因,如果我这样做,它就会按预期工作......
For whatever reason, it works as expected if I do like this...
当 XAML 文件编译为 BAML 时,它引用程序集而不是内存中的源。 由于 BAML 被编译到同一程序集中,因此实际类型尚不可用。
我发现一个短期解决方法是暂时注释掉样式,构建项目,然后恢复样式。
然而,更永久的解决方案是将转换器移至另一个组件。
When the XAML files are compiled to BAML it references the assembly not the in memory source. Since the BAML is compiled into the same assembly the actual type isn't available yet.
I've found that a short term workaround is to comment out the style temporarily, build the project, then restore the style.
The more permanent solution however is to move the converter to another assembly.
在更高级别声明一次
FooConverter
(可能作为DataGrid
的资源)而不是在每个DataTemplate
中声明一次是否有帮助?Would it help to declare the
FooConverter
once at a higher level (maybe as a resource of theDataGrid
) instead of in eachDataTemplate
?