【问题标题】:How to create a DataTemplate using C# and set child control's resources?如何使用 C# 创建 DataTemplate 并设置子控件的资源?
【发布时间】:2020-06-15 09:11:57
【问题描述】:

我将如何为代码中的特定控件创建一些资源?

此数据模板定义列表视图的列应如何呈现其内容。但是,由于此视图的特殊性质,我必须在代码中创建列以正确分配所需的属性。一切正常,唯一的例外是我没有找到将内容控件的内部数据模板分配给代码中内容控件的资源字典的正确方法(这是必需的,因为它会根据绑定的类型而变化,想象一下“...”中定义的其他模板)。我唯一缺少的部分是来自 xaml 的 <ContentControl.Resources> 的“翻译”。

<DataTemplate>
    <ContentControl Content="{Binding}" Focusable="False">
        <ContentControl.Resources>
            <DataTemplate DataType="{x:Type data:DataItem}">
                <StackPanel Orientation="Horizontal">
                    <TextBox Text="{Binding FirstProperty}"/>
                    <Label Content=" - "/>
                    <TextBox Text="{Binding SecondProperty}"/>
                </StackPanel>
            </DataTemplate>
            ...
        </ContentControl.Resources>
    </ContentControl>
</DataTemplate>

这是我目前的cs代码:

private DataTemplate GenerateSomeTemplate()
{
    DataTemplate template = new DataTemplate(typeof(TextBlock));
    FrameworkElementFactory contentElement = new FrameworkElementFactory(typeof(ContentControl));
    template.VisualTree = contentElement;
    contentElement.SetBinding(ContentControl.ContentProperty, new Binding() { }); // Might be wrong
    contentElement.SetValue(ContentControl.FocusableProperty, false);

    var displayTemplate = new DataTemplate(typeof(DataItem));
    var layout = new FrameworkElementFactory(typeof(StackPanel));

    var textBoxFirst = new FrameworkElementFactory(typeof(TextBox));
    textBoxFirst.SetBinding(TextBox.TextProperty, new Binding() { Path = new PropertyPath("FirstProperty") });
    layout.AppendChild(textBoxFirst);

    var dashLabel = new FrameworkElementFactory(typeof(Label));
    dashLabel.SetValue(Label.ContentProperty, " - ");
    layout.AppendChild(dashLabel);

    var textBoxSecond = new FrameworkElementFactory(typeof(TextBox));
    textBoxFirst.SetBinding(TextBox.TextProperty, new Binding() { Path = new PropertyPath("SecondProperty") });
    layout.AppendChild(textBoxSecond);

    displayTemplate.VisualTree = layout;

    // contentElement.AddResource(displayTemplate); // I need something like this...

    return template;
}

【问题讨论】:

  • 您是否考虑过使用 xamlreader.parse 并将此列定义构建为字符串?这是动态构建 UI 的推荐方法。它提供了一个显着的好处,即您可以在出现问题时抓住您的字符串并进行尝试。

标签: c# wpf resources controls datatemplate


【解决方案1】:

FrameworkElementFactory:

这个类是一种以编程方式创建模板的弃用方式,模板是 FrameworkTemplate 的子类,例如 ControlTemplate 或 DataTemplate;使用此类创建模板时,并非所有模板功能都可用。以编程方式创建模板的推荐方法是使用 XamlReader 类的 Load 方法从字符串或内存流加载 XAML。

这意味着,您应该使用XmlReader 从字符串中激活DataTemplate

var dataTemplateString = 
  @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" 
                  xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">    
      <ContentControl Content=""{Binding}"" Focusable=""False"">
        <ContentControl.Resources>
          <DataTemplate DataType=""{x:Type data:DataItem}"">
            <StackPanel Orientation=""Horizontal"">
              <TextBox Text=""{Binding FirstProperty}""/>
              <Label Content="" - ""/>
              <TextBox Text=""{Binding SecondProperty}""/>
            </StackPanel>
          </DataTemplate>
        </ContentControl.Resources>
      </ContentControl>
    </DataTemplate>";

var stringReader = new StringReader(dataTemplateString);
XmlReader xmlReader = XmlReader.Create(stringReader);
DataTemplate dataTemplate = (DataTemplate) XamlReader.Load(xmlReader);

或者,您可以使用XamlWriter.Save() 序列化现有的DataTemplate,然后使用XamlReader.Load() (Serialization Limitations of XamlWriter.Save) 实际激活它。

还有一个在运行时加载 XAML 对象的异步实现:XamlReader.LoadAsync

【讨论】:

  • 太棒了,这听起来完全符合我的需要!但是,我收到以下错误:System.Windows.Markup.XamlParseException:''无法创建未知类型'DataTemplate'。'行号“1”和行位置“2”。我在文件中使用了正确的“使用”语句,但是......这可能是什么原因?
  • 我是否必须以某种方式手动加载 XamlReader 中的程序集?
  • @SushiYetiDev 我已经更新了答案。是的,您必须将所有必需的命名空间添加到标记中(包括自定义和框架命名空间)。您可以将它们全部添加到根元素或引用类型的元素。此外,字符串需要正确的字符转义。我之前只是复制了你的代码。我现在已经对其进行了更新,以便该示例可以编译。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-11
  • 1970-01-01
  • 2022-07-24
  • 1970-01-01
  • 1970-01-01
  • 2021-01-05
相关资源
最近更新 更多