WPF styles for reference type DependencyProperty

612 views Asked by At

I have problem related to WPF styles. Let's use class (or prepare such) to contain DependencyProperty.

public class MyProperty : DependencyObject
{
    public static readonly DependencyProperty exampleValueProperty = DependencyProperty.Register("exampleValue", typeof(bool), typeof(MyProperty));

    public bool exampleValue
    {
        get { return (bool)this.GetValue(exampleValueProperty); }
        set { this.SetValue(exampleValueProperty, value); }
    }
}

public class MyTextBlock : TextBlock
{
    public static readonly DependencyProperty myPropertyProperty= DependencyProperty.Register(
        "myProperty", typeof(MyProperty), typeof(MyTextBlock));
    public MyProperty myProperty
    {
        get
        {
            return (MyProperty)this.GetValue(myPropertyProperty);
        }
        set
        {
            this.SetValue(myPropertyProperty, value);
        }
    }
}

Now define style in xaml file and put 2 objects of class MyTextBlock on my main window grid:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:custom="clr-namespace:WpfCustomControlLibrary1;assembly=WpfCustomControlLibrary1"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <ResourceDictionary>
        <Style TargetType="{x:Type custom:MyTextBlock}">
            <Setter Property="Background" Value="Aqua" />
            <Setter Property="myProperty">
                <Setter.Value>
                    <custom:MyProperty exampleValue="true" />
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
</Window.Resources>
<Grid RenderTransformOrigin="0.514,0.47" Margin="100,0,0,0">
    <custom:MyTextBlock x:Name="textBlock1" Height="80" Width="80" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,104,62.8,0" />
    <custom:MyTextBlock x:Name="textBlock2" Height="80" Width="80" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,200,62.8,0" />
</Grid>
</Window>

And now the problem, when I change exampleValue for false using:

textBlock1.myProperty.exampleValue = false;

exampleValue is changed also for textBlock2.

As I can see, both textBlock1.myProperty and textBlock2.myProperty return same hashCode. Probably this is because we firstly create one object of myProperty and then Setter just assign it (copy) to each MyTextBlock object. Is there any way to use clone here? So every object will have his own "myProperty"?

I know that this one will works correctly, if I define my properties per object (but it looks like workaround, not solution):

<custom:MyTextBlock x:Name="textBlock1" Height="80"  HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,104,62.8,0">
    <custom:MyTextBlock.myProperty>
        <custom:MyProperty exampleValue="False"/>
    </custom:MyTextBlock.myProperty>
</custom:MyTextBlock>
<custom:MyTextBlock x:Name="textBlock2" Height="80"  HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,200,62.8,0">
    <custom:MyTextBlock.myProperty>
        <custom:MyProperty exampleValue="False"/>
    </custom:MyTextBlock.myProperty>
</custom:MyTextBlock>
1

There are 1 answers

0
lidqy On BEST ANSWER

It's the same instance of "MyProperty" because you create it as a resource. And resources are shared / static by default. Maybe setting "x:Shared" to false, might help:

<ResourceDictionary>
    <Style TargetType="{x:Type custom:MyTextBlock}" x:Shared="false">
        <Setter Property="Background" Value="Aqua" />
        <Setter Property="myProperty">
            <Setter.Value>
                <custom:MyProperty exampleValue="true" />
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Anyhow I am not sure if it will do the trick, because it's the default, keyless style of your MyTextBlock control and it might be cached anyhow.

If it works than you have one instance of MyProperty for each MyTextBlock control but still with the same value for "exampleValue".

EDIT: Sorry didn't see @Brannon s comment ;)