【问题标题】:dynamic datatemplate with valueconverter带有值转换器的动态数据模板
【发布时间】:2009-03-16 22:03:20
【问题描述】:

我想在 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
}

候选人列表中的候选人数量可在运行时配置。

所需的网格布局如下所示

Foo | Bar | Candidate 1 | Candidate 2 | ... | Candidate N

因此,我似乎无法在 xaml 中为候选者创建 DataTemplate,因为绑定表达式会发生变化。

我在 AutoGeneratedColumns 事件中添加必要的列,如下所示:

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] 是硬编码的。

【问题讨论】:

    标签: c# wpf xaml datatemplate valueconverter


    【解决方案1】:

    无论出于何种原因,如果我这样做,它会按预期工作......

        string assName = Assembly.GetExecutingAssembly().GetName().Name;
        StringBuilder sb = new StringBuilder();
        sb.Append("<DataTemplate ");
        sb.Append("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' ");
        sb.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' ");
        sb.Append("xmlns:src='clr-namespace:WpfToolkitDataGridTester;assembly=" + assName + "' >");
        sb.Append("<DataTemplate.Resources>");
        sb.Append("<src:FooConverter x:Key='fooConverter' />");
        sb.Append("</DataTemplate.Resources>");
        sb.Append("<TextBlock ");
        sb.Append("Foreground='{Binding Candidates[" + i + "].CandidateType,Converter={StaticResource fooConverter}}' ");
        sb.Append("Text='{Binding Candidates[" + i + @"].Name}' />");
        sb.Append("</DataTemplate>");
        var template = (DataTemplate)XamlReader.Parse(sb.ToString());
    

    【讨论】:

      【解决方案2】:

      当 XAML 文件被编译为 BAML 时,它引用 程序集 而不是内存中的源。由于 BAML 被编译到同一个程序集中,因此实际类型尚不可用。

      我发现一个短期的解决方法是暂时注释掉样式,构建项目,然后恢复样式。

      然而,更持久的解决方案是将转换器移至另一个组件。

      【讨论】:

        【解决方案3】:

        在更高级别(可能作为DataGrid 的资源)而不是在每个DataTemplate 中声明一次FooConverter 会有所帮助吗?

        【讨论】:

        • 我也试过了,也没用。我认为部分原因是如果它不在要解析的字符串中,XamlParser 将找不到它。
        猜你喜欢
        • 2014-07-22
        • 2019-04-30
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 2015-07-14
        • 2016-12-01
        • 2014-03-25
        • 2018-04-25
        相关资源
        最近更新 更多