DataTemplate Shared State
I have a newbie question that I'm unable to answer despite my best efforts.
I am storing SVG geometry in a resource dictionary using DataTemplate.
I assign this DataTemplate to a ContentControl.
I find that if I set the color of the paths,it sets the color for all future instances of this resource when retrieved from the dictionary.
Thank you for considering my question! :)
I am storing SVG geometry in a resource dictionary using DataTemplate.
Code: Select all
<DataTemplate x:Key="chair_svg">
<Viewbox>
<Canvas Width="160" Height="160">
<Path Fill="#ffffff" Data="M55.8105 25.5325V60.9405L50.8313 58.1743H43.639L41.9793 65.9198H46.3461L43.1889 95.4487L39.7663 97.455V100.775H42.6195L37 140H45.2988L48.6043 100.775H52.7676L54.0378 116.017C54.4552 121.025 57.2971 125.512 61.6465 128.03C63.9846 129.384 66.6384 130.097 69.3401 130.097H96.5339C98.4845 130.097 100.397 129.556 102.058 128.533C104.975 126.738 106.838 123.638 107.053 120.22L108.28 100.775H112.844L116.115 139.447H123.86L117.646 100.775H122.754V97.455L116.863 94.2247L113.415 65.3665H117.775V58.7275H109.384L104.497 61.0124V25.5325L101.177 20H57.4703L55.8105 25.5325ZM52.6476 65.9198H55.8105V83.3333L104.497 82.2222V66.3821L107.683 65.8583L105.823 88.1707L105.603 88.0498H104.497H55.8105L54.7917 88.647L52.6476 65.9198ZM55.9358 100.775L57.502 117.376C57.8278 120.83 59.8582 123.892 62.9126 125.537C64.4244 126.351 66.1146 126.777 67.8316 126.777H95.9959C97.2168 126.777 98.4176 126.466 99.4849 125.873C101.58 124.709 102.956 122.578 103.155 120.19L104.773 100.775H55.9358ZM51.8983 90.3431L50.395 72.303L49.1594 91.9487L51.8983 90.3431ZM108.966 89.8939L112.274 91.7079L110.618 65.3759L110.511 65.3934L108.966 89.8939Z" />
</Canvas>
</Viewbox>
</DataTemplate>
Code: Select all
DataTemplate dataTemplate = root.TryFindResource(resourceKey) as DataTemplate;
ContentControl contentControl = new ContentControl();
contentControl.IsTabStop = false;
if (dataTemplate != null)
contentControl.ContentTemplate = dataTemplate;
Code: Select all
public static void SetPathBrush(Visual root, Brush brush)
{
// likely slower
//foreach (Path path in root.FindVisualChildren<Path>())
// path.Fill = brush;
if (root == null)
return;
try
{
if (root is Path path)
{
if (path.Fill is SolidColorBrush solidColorBrush)
{
if (solidColorBrush.Color != Colors.Transparent)
path.Fill = brush;
}
}
else if (root is Viewbox viewbox)
SetPathBrush(viewbox.Child, brush);
else if (root is ContentControl contentControl)
SetPathBrush((Visual)contentControl.Content, brush);
else if (root is Panel panel)
foreach (UIElement uiElement in panel.Children)
SetPathBrush(uiElement, brush);
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e);
}
}
- Since a data template is used sharing of state is by design, right?
- If I do not want the state to be shared, should I use something besides a DataTemplate in the ResourceDictionary?
- Or is there an alternative way of assigning the template to the ContentControl so that subsequent state may be modified?
Thank you for considering my question! :)
Re: DataTemplate Shared State
Databinding approach:
Code: Select all
<DataTemplate x:Key="example_svg">
<Viewbox>
<Canvas Width="160" Height="160">
<Canvas>
<Path Fill="{Binding DataContext.Fill, RelativeSource={RelativeSource AncestorType=ContentControl}, FallbackValue=#ffffff}" Data="..." />
</Canvas>
</Canvas>
</Viewbox>
</DataTemplate>
Code: Select all
public class DataModelExample
{
public Brush Fill { get; set; } = Brushes.Blue;
}
DataTemplate dataTemplate = root.TryFindResource("example_svg") as DataTemplate;
contentControl.ContentTemplate = dataTemplate;
myContentControl.DataContext = new DataModelExample { Fill = Brushes.DimGray };
-
sfernandez
Site Admin
- Posts: 3188
- Joined:
Re: DataTemplate Shared State
Yes, template is shared, so if you modify it, all the instances generated from that template will have the modified values.Since a data template is used sharing of state is by design, right?
As you just posted, using bindings is a good way of customizing the contents of a template. This is how it works for normal controls like Buttons, that have a Border in the template bound to the Background/BorderBrush properties of the Button, so you can change the color from outside.If I do not want the state to be shared, should I use something besides a DataTemplate in the ResourceDictionary?
Or is there an alternative way of assigning the template to the ContentControl so that subsequent state may be modified?
Just a tip, as DataContext is inherited down the visual tree, if you set it in the control, you can probably bind directly to the Fill property if the viewmodel is set as the Content, have you tried that?
Code: Select all
<DataTemplate x:Key="example_svg">
<Viewbox>
<Canvas Width="160" Height="160">
<Canvas>
<Path Fill="{Binding Fill, FallbackValue=#ffffff}" Data="..." />
</Canvas>
</Canvas>
</Viewbox>
</DataTemplate>
Code: Select all
DataTemplate dataTemplate = root.TryFindResource("example_svg") as DataTemplate;
myContentControl.ContentTemplate = dataTemplate;
myContentControl.Content = new DataModelExample { Fill = Brushes.DimGray };
Re: DataTemplate Shared State
Confirmed that it works! Thank you for the improved data binding solution!
Who is online
Users browsing this forum: Bing [Bot] and 5 guests