Create DataTemplate in code behind

前端 未结 3 746
野的像风
野的像风 2020-11-27 05:12

How do i add controls to datatemplates programmatically?

For Example. Below I\'ve created TextBlock and DataTemplate.

TextBlock text = new TextBlock(         


        
相关标签:
3条回答
  • 2020-11-27 05:36

    I know it is an work-around, but I published a tip in code project (http://www.codeproject.com/Tips/808808/Create-Data-and-Control-Templates-using-Delegates) that allows you to create a data-template using a delegate. For example:

    TemplateGenerator.CreateDataTemplate(() => new TextBox());
    

    This will be enough to create a datatemplate that creates a new textbox. If you want a binding too, it could be written like:

    TemplateGenerator.CreateDataTemplate
    (
      () =>
      {
        var result = new TextBox();
        result.SetBinding(TextBox.TextProperty, "PathForTheBinding");
        return result;
      }
    );
    

    The code of the TemplateGenerator is the following:

    /// <summary>
    /// Class that helps the creation of control and data templates by using delegates.
    /// </summary>
    public static class TemplateGenerator
    {
      private sealed class _TemplateGeneratorControl:
        ContentControl
      {
        internal static readonly DependencyProperty FactoryProperty = DependencyProperty.Register("Factory", typeof(Func<object>), typeof(_TemplateGeneratorControl), new PropertyMetadata(null, _FactoryChanged));
    
        private static void _FactoryChanged(DependencyObject instance, DependencyPropertyChangedEventArgs args)
        {
          var control = (_TemplateGeneratorControl)instance;
          var factory = (Func<object>)args.NewValue;
          control.Content = factory();
        }
      }
    
      /// <summary>
      /// Creates a data-template that uses the given delegate to create new instances.
      /// </summary>
      public static DataTemplate CreateDataTemplate(Func<object> factory)
      {
        if (factory == null)
          throw new ArgumentNullException("factory");
    
        var frameworkElementFactory = new FrameworkElementFactory(typeof(_TemplateGeneratorControl));
        frameworkElementFactory.SetValue(_TemplateGeneratorControl.FactoryProperty, factory);
    
        var dataTemplate = new DataTemplate(typeof(DependencyObject));
        dataTemplate.VisualTree = frameworkElementFactory;
        return dataTemplate;
      }
    
      /// <summary>
      /// Creates a control-template that uses the given delegate to create new instances.
      /// </summary>
      public static ControlTemplate CreateControlTemplate(Type controlType, Func<object> factory)
      {
        if (controlType == null)
          throw new ArgumentNullException("controlType");
    
        if (factory == null)
          throw new ArgumentNullException("factory");
    
        var frameworkElementFactory = new FrameworkElementFactory(typeof(_TemplateGeneratorControl));
        frameworkElementFactory.SetValue(_TemplateGeneratorControl.FactoryProperty, factory);
    
        var controlTemplate = new ControlTemplate(controlType);
        controlTemplate.VisualTree = frameworkElementFactory;
        return controlTemplate;
      }
    }
    

    And it has a method for ControlTemplates too.

    0 讨论(0)
  • 2020-11-27 05:40

    Although Archedius's method works, officially it is deprecated and instead recommended way to programmatically create a template is to load XAML from a string or a memory stream using the Load method of the XamlReader class like this...

    public DataTemplate Create(Type type)
    {
        StringReader stringReader = new StringReader(
        @"<DataTemplate 
            xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""> 
                <" + type.Name + @" Text=""{Binding " + ShowColumn + @"}""/> 
            </DataTemplate>");
        XmlReader xmlReader = XmlReader.Create(stringReader);
        return XamlReader.Load(xmlReader) as DataTemplate;
    }
    

    Official line taken from msdn: http://msdn.microsoft.com/en-us/library/system.windows.frameworkelementfactory.aspx

    Code example from Fredrik Hedblad's post here: Problems with XamlReader generating DataTemplate

    0 讨论(0)
  • 2020-11-27 05:41

    You have first to declare a DataTemplate:

    DataTemplate template = new DataTemplate { DataType = typeof(< Type of the object the template refers>) };
    

    Then declare a layout panel like StackPanel in this way

    FrameworkElementFactory stackPanelFactory = new FrameworkElementFactory(typeof(StackPanel));
    stackPanelFactory.SetValue(StackPanel.OrientationProperty, Orientation.Vertical);
    

    and finally attach the TextBlock piece at it:

    FrameworkElementFactory title = new FrameworkElementFactory(typeof(TextBlock));
    title.SetBinding(TextBlock.TextProperty, new Binding("< name of your binding >"));
    stackPanelFactory.AppendChild(title);
    

    in order to display the StackPanel created in this way you have to attach it to the VisualTree:

    template.VisualTree = stackPanelFactory;
    

    Hope it helps! :)

    0 讨论(0)
提交回复
热议问题