I want to do the following at runtime in code:
<DataTemplate x:Key="lightGreenRectangle">
<Rectangle Fill="LightGreen"/>
</DataTemplate>
So far I've got:
public DataTemplate GetColouredRectangleInDataTemplate(Color colour)
{
DataTemplate dataTemplate = new dataTemplate();
return dataTemplate;
}
Help? I know this isn't the most elegant way of styling a control, but the component I want to specify a colour for has a property called "PointTemplate" of type DataTemplate.
According to Microsofts App Studio the DataTemplates should live in a DataTemplates Subdirectory under the Views Directory.
DataTemplate is about the presentation of data and is one of the many features provided by the WPF styling and templating model. For an introduction of the WPF styling and templating model, such as how to use a Style to set properties on controls, see the Styling and Templating topic.
You use the ItemTemplate to specify the visualization of the data objects. If your ItemsControl is bound to a collection object and you do not provide specific display instructions using a DataTemplate, the resulting UI of each item is a string representation of each object in the underlying collection.
If for whatever reason you need to create a DataTemplate
programmatically you would do:
XAML:
<Grid x:Name="myGrid">
<ContentControl ContentTemplate="{DynamicResource lightGreenRectangle}" />
</Grid>
Somewhere in your code:
public static DataTemplate CreateRectangleDataTemplate()
{
var rectangleFactory = new FrameworkElementFactory(typeof(Rectangle));
rectangleFactory.SetValue(Shape.FillProperty, new SolidColorBrush(System.Windows.Media.Colors.LightGreen));
return new DataTemplate
{
VisualTree = rectangleFactory,
};
}
public static void AddRectangleTemplateToResources(FrameworkElement element)
{
element.Resources.Add("lightGreenRectangle", CreateRectangleDataTemplate());
}
Then you just need to add the DataTemplate
to a ResourceDictionary
so it can be used. For example, in the code behind:
public MainWindow()
{
InitializeComponent();
AddRectangleTemplateToResources(myGrid);
}
Hope this helps!
Using the following helper class:
/// <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;
}
}
You can create a data-template like this:
DataTemplate template =
TemplateGenerator.CreateDataTemplate
(
() =>
{
var result = new TextBox()
result.SetBinding(TextBox.TextProperty, "BindingPathHere");
return result;
}
);
You are free to use any code to create the control as you will do if you were creating the control directly, without any data-template. For more info, see this tip in code project: http://www.codeproject.com/Tips/808808/Create-Data-and-Control-Templates-using-Delegates
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With