How to Programmatically Modify a DataTemplate? - silverlight

I'm trying to programmatically add events and elements to a DataTemplate in a Silverlight 3.0 app. I have a User Control with a dependency property where I would like to take the template that's set, tweak it, and then set the modified version to an inner control.
The idea I have is to take the DataTemplate that comes in, read its XAML, tweak it, and then use the XamlReader to create a modified DataTemplate that can then be set to the inner control. The issue with this approach is I don't know how to get the XAML from the originalal template (if it's even possible.) For example:
protected virtual void OnItemTemplateChanged(DependencyPropertyChangedEventArgs e)
{
// Get the original Xaml from the set template
//string originalXaml = ???
// Modify the template
string newXaml = originalXaml.Replace("foo", "bar"); // for example
// Create a new template from the modified XAML
DataTemplate newTemplate = (DataTemplate)XamlReader.Load(newXaml);
// Update the inner template
this._childDropdown.ItemTemplate = newTemplate;
}
Does someone know either: 1) if there's a way to read the original XAML, or 2) another approach to programmatically modify the DataTemplate.
Thanks,

You cannot manipulate the template via code (see documentation for FrameworkTemplate). The closest you are going to get is to call the DataTemplate's LoadContent to create an instance of the contained Xaml but you can't use that to manipulate the contents and there is no way inside Silverlight to convert a UIElement back to Xaml again.
The nearest I think you can get is to make your dependency object a Uri pointing to a Xaml resource that contains the initial DataTemplate.
You can then load this resource into an XDocument and manipulate it as XML. Subsequently you can use XamlReader to instance the DataTemplate and assign it to ItemTemplate.

Related

WPF Datagrid Button commandParameter in code behind

I'm trying to build a datagrid with columns and a button in code behind and I want to assign the command parameter of this button to the value of the "ID" column which is "TDENT_ID". Here's my code
this line is not working as you can see :
BtnDetail.SetBinding(System.Windows.Controls.Primitives.ButtonBase.CommandParameterProperty, new Binding() { Source = dtGrid, Path = "TDENT_ID" });
How can I write it?
FrameworkElementFactory:
"This class is a deprecated way to programmatically create templates, which are subclasses of FrameworkTemplate such as ControlTemplate or DataTemplate; not all of the template functionality is available when you create a template using this class. The 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." Microsoft Docs
Your Bindingis wrong. It currently points to the DataGrid which does not have a property TDENT_ID.
This property is on your data item, which is the DataContext of the column's template.
Therefore, correct Binding would be:
// Set up a Binding that uses the current DataContext as Binding.Source
BtnDetail.SetBinding(ButtonBase.CommandParameterProperty, new Binding(nameof(myItemType.TDENT_ID)));
Microsoft Docs: Specifying the binding source
Try to learn XAML. It makes writing such UI related code much easier, which makes you more productive.

What's the best way to give a dependency property a default value from a resource dictionary

I'd like to create a WPF user control (or custom control). The user of this control should be able to re-template a certain part of this control. For that I created a dependency property called "SubTemplate".
Public Shared ReadOnly SubTemplateProperty As DependencyProperty =
DependencyProperty.Register("SubTemplate", GetType(DataTemplate), GetType(MyControl), New FrameworkPropertyMetadata(Nothing))
Of course there should be a default template that's used, when the user doesn't give it's own template. But how do I give this default value to the dependency property?
I'd like to define this default template in XAML (probably in a resource dictionary, maybe in Themes\Generic.xaml?)
Is there a way to exchange the Nothing default value with a template from a resource dictionary?
Or do I have to set the default value in the constructor of my control (still don't know how to access a named template from a resource dictionary in code behind, FindResource doesn't seem to work or I'm using it wrong).
Or do I have to set the TargetNullValue of the binding I use to add the template to the re-templated part of the control?
Right now I just set the "SubTemplate" property in the default style of my control, but if the user restyles the whole control and forgets to give a "SubTemplate", then it would be Nothing.
Is there a way to exchange the Nothing default value with a template from a resource dictionary?
If you add the default DataTemplate to your App.xaml file, this should work:
Public Shared ReadOnly SubTemplateProperty As DependencyProperty =
DependencyProperty.Register("SubTemplate", GetType(DataTemplate), GetType(MyControl), New FrameworkPropertyMetadata(Application.Current.Resources("KeyOfTemplate")))
If you want more control over things you could write some code that looks up the template, for example in the OnApplyTemplate method of the control. You may want to get it from somewhere else, check that it actually exists, etc.

Convert UIElement to DataTemplate

I have a DataTemplate defined in XAML. I want to customize it and give it to DataGridTemplateColumn.CellTemplate. But when I call LoadContent(), the VisualTree is still null, instead a UIElement tree is returned. After I customize the tree, how can I convert it back to a DataTemplate? Or is there a way to feed the DataGrid cells directly with UIElement?
I think it should help you
Code Project
I've learned that once the UI controls are instantiated, it is impossible to convert back to a DataTemplate i.e. FrameworkElementFactory tree.

Add DependencyObject to control from code-behind

I want to add a DependencyObject to a control from code behind. I have searched and searched online for how to do this with absolutely no success. The DependencyObject has a DependencyProperty. I also want to set this property from code-behind.
charting:ChartBehaviors inherits directly from DependencyObject. It is a class I wrote myself. The Chart control is a Third-party control.
charting:ChartBehaviors.FloatingTooltip is the DependencyProperty. This is also a class I wrote myself.
Here is what it looks like in XAML. I want to do this in code behind so that I can turn on and off the "behavior".
<charting:Chart>
<charting:ChartBehaviors.FloatingTooltip>
<charting:FloatingTooltipBehavior
TooltipTemplate="{StaticResource tooltipTemplate}" />
</charting:ChartBehaviors.FloatingTooltip>
</charting:Chart>
You can just use the SetValue method on the object (assuming you give your chart an id of chart1).
var behave = new FloatingTooltipBehavior();
chart1.SetValue(ChartBehaviors.FloatingTooltipProperty, behave);
Another solution would be to just add an Enabled property to your behavior and then set that from the code behind.
Well, you basically instantiate necessary dependency object and use appropriate method to add it to the control. For example, to add TextBlock to the StackPanel, you write it like this:
TextBlock txtMyText = new TextBlock();
stackPanel.Children.Add(txtMyText);
If you're wanting to add certain behavior to a chart, you should just get your chart object in code and look for a property like Behaviors or something. Then you either assign a behavior (if it's one-behavior-only) or add it like to the stackpanel:
Chart myChart;
myChart.Behavior = new FloatingTooltipBehavior();
It's hard to tell the exact syntax without knowing the component.

How to replace a ResourceDictionary of a 3rd Party UserControl (in this case PivotViewer)

The current version of the Microsoft Live Labs PivotViewer control for SilverLight 4 has no way to style the elements of the control. Looking at the control in Reflector, I can see much of the style info is set in a ResourceDictionary in the assembly (assets/defaultcolors.xaml). What I would like to do is create my own copy of this file, then replace it at runtime on the PivotViewer control.
By subclassing the PivotViewer control and overriding OnApplyTemplate I can grab the child elements and set properties such as Background. I have not had any success Clear()'ng the MergedDictionaries and adding in my own:
public override void OnApplyTemplate() {
base.OnApplyTemplate();
/* can change things this way */
CollectionViewerView cvv = ((CollectionViewerView)((Grid)this.GetTemplateChild("PART_Container")).Children[0]);
((Grid)cvv.Content).Background = new SolidColorBrush(Colors.Black);
/* can't change things this way */
CustomDictionary gd = new CustomDictionary();
cvv.Resources.MergedDictionaries.Clear();
cvv.Resources.MergedDictionaries.Add(gd);
}
I'm afraid this isn't going to work in Silverlight because it uses only Static Resources. ( Styles Don't Update )
Changing a resource dictionary only works before InitializeComponent() is called, which is called in the constructor of the PivotViewer.
I've been trying to style the PivotViewer Control too. I hope there is another way, besides searching through the Visual Tree and changing properties.

Resources