Changing a property in a custom control changes all elements of that type.
Like the title says, when I change a property of a control it inconsistently changes all controls of that type as well.
I attached a project that recreates this. In Assets/Views/Root.xaml, if you set the last NineSlice control's ImageSource property to "{StaticResource AltBorder}" it will change all of the NineSlice controls' ImageSource. You will also notice that the first NineSlice control is set to AltBorder, but it does not show as such.
This also shows the problem I submitted here about RelativeSource TemplatedParent not working correctly - I am forced to set that property in the code behind.
Project:
I attached a project that recreates this. In Assets/Views/Root.xaml, if you set the last NineSlice control's ImageSource property to "{StaticResource AltBorder}" it will change all of the NineSlice controls' ImageSource. You will also notice that the first NineSlice control is set to AltBorder, but it does not show as such.
This also shows the problem I submitted here about RelativeSource TemplatedParent not working correctly - I am forced to set that property in the code behind.
Project:
-
sfernandez
Site Admin
- Posts: 2991
- Joined:
Re: Changing a property in a custom control changes all elements of that type.
As described in this post: viewtopic.php?f=3&t=2052
you are sharing the same resource for all controls, so the last control that sets the ImageSource property of the resource is changing it for all instances of the control.
You should define the resources inside the visual tree so they can be different for each instance:
you are sharing the same resource for all controls, so the last control that sets the ImageSource property of the resource is changing it for all instances of the control.
You should define the resources inside the visual tree so they can be different for each instance:
Code: Select all
<Style TargetType="{x:Type local:NineSlice}">
<Setter Property="ImageSource" Value="{StaticResource DefaultBorder}" />
<Setter Property="SliceThickness" Value="4" />
<Setter Property="BorderThickness" Value="20" />
<Setter Property="Padding" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:NineSlice}">
<Grid x:Name="Root">
<Grid.Resources>
<Style TargetType="Rectangle">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="RenderOptions.BitmapScalingMode" Value="NearestNeighbor" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding BorderThickness.Left, RelativeSource={RelativeSource TemplatedParent}}" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="{Binding BorderThickness.Right, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding BorderThickness.Top, RelativeSource={RelativeSource TemplatedParent}}" />
<RowDefinition Height="*" />
<RowDefinition Height="{Binding BorderThickness.Bottom, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid.RowDefinitions>
<Rectangle x:Name="TopLeft" Grid.Row="0" Grid.Column="0">
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageSource}"
ViewboxUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="TopCenter" Grid.Row="0" Grid.Column="1">
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageSource}"
ViewboxUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="TopRight" Grid.Row="0" Grid.Column="2">
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageSource}"
ViewboxUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="CenterLeft" Grid.Row="1" Grid.Column="0">
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageSource}"
ViewboxUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="CenterRight" Grid.Row="1" Grid.Column="2">
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageSource}"
ViewboxUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="BottomLeft" Grid.Row="2" Grid.Column="0">
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageSource}"
ViewboxUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="BottomCenter" Grid.Row="2" Grid.Column="1">
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageSource}"
ViewboxUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="BottomRight" Grid.Row="2" Grid.Column="2">
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageSource}"
ViewboxUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Grid x:Name="Middle" Grid.Row="1" Grid.Column="1">
<Rectangle x:Name="Center">
<Rectangle.Fill>
<ImageBrush
ImageSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageSource}"
ViewboxUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<ContentPresenter x:Name="MiddleContent" Margin="{TemplateBinding Padding}" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Code: Select all
public NineSlice()
{
Loaded += (s, e) =>
{
ApplyTemplate();
_root = (Grid)Template.FindName("Root", this);
if (_root != null)
{
_tLeft = (ImageBrush)((Rectangle)Template.FindName("TopLeft", this)).Fill;
_t = (ImageBrush)((Rectangle)Template.FindName("TopCenter", this)).Fill;
_tRight = (ImageBrush)((Rectangle)Template.FindName("TopRight", this)).Fill;
_cLeft = (ImageBrush)((Rectangle)Template.FindName("CenterLeft", this)).Fill;
_c = (ImageBrush)((Rectangle)Template.FindName("Center", this)).Fill;
_cRight = (ImageBrush)((Rectangle)Template.FindName("CenterRight", this)).Fill;
_bLeft = (ImageBrush)((Rectangle)Template.FindName("BottomLeft", this)).Fill;
_b = (ImageBrush)((Rectangle)Template.FindName("BottomCenter", this)).Fill;
_bRight = (ImageBrush)((Rectangle)Template.FindName("BottomRight", this)).Fill;
UpdateRects();
}
};
}
Re: Changing a property in a custom control changes all elements of that type.
But doesn't this work in WPF? And the same with the other problem? I have multiple NineSlice controls with different borders and none are changing when I change an individual ImageSource. Please correct me if I'm wrong, but there doesn't seem to be any problem with this. Sorry for being so WPF centric in these posts, but I usually test my problem in WPF before posting here, so it's odd that I can't seem to make it break in WPF.
- Attachments
-
- WpfApp4.rar
- (97.87 KiB) Downloaded 101 times
-
sfernandez
Site Admin
- Posts: 2991
- Joined:
Re: Changing a property in a custom control changes all elements of that type.
Sorry, I was doing a different test , defining the resource in ControlTemplate.Resources, instead of the resources of an element of the Template visual tree.
I have verified we are deviating from WPF in case resources are part of the Resources property of an element in the Template visual tree.
I created a ticket #1759 to follow this issue. In the meantime the workaround is as I said, define the ImageBrush directly in the Rectangles, instead of using StaticResources, sorry for the inconvenience.
I have verified we are deviating from WPF in case resources are part of the Resources property of an element in the Template visual tree.
I created a ticket #1759 to follow this issue. In the meantime the workaround is as I said, define the ImageBrush directly in the Rectangles, instead of using StaticResources, sorry for the inconvenience.
Re: Changing a property in a custom control changes all elements of that type.
No problem! Thank you so much for helping me. And just to make sure I understand, this and my other thread both stems from the same problem that is explained in that bug report?
-
sfernandez
Site Admin
- Posts: 2991
- Joined:
Re: Changing a property in a custom control changes all elements of that type.
Yes, the source of the problem is the same. As the resource is being shared, TemplatedParent binding can't be correctly resolved, and also, changing a property on that resource affects all controls.
Who is online
Users browsing this forum: No registered users and 10 guests