Why is a custom property in a UserControl not set when the control is used in a DataTemplate?
Asked Answered
C

2

7

I have a UserControl that has a custom DependencyProperty. When I use the UserControl from inside a DataTemplate, I cannot set the value of the DependencyProperty. If I use the UserControl directly in a window, then the DependencyProperty works fine. I apologize for the long post, I simplified the code to the minimum that still shows the problem I have in my project. Thanks for any help, I don't know what else to try.

Main Window XAML:

<Window ...>
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:TextVM}">
            <local:TextV MyText="I do not see this"/> <!--Instead I see "Default in Constructor"-->
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Border BorderThickness="5" BorderBrush="Black" Width="200" Height="100" >
            <StackPanel>
                <ContentControl Content="{Binding Path=TheTextVM}"/>
                <local:TextV MyText="I see this"/>
            </StackPanel>
        </Border>
    </Grid>
</Window>

Main Window Code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        TheTextVM = new TextVM();
    }

    public TextVM TheTextVM { get; set; }
}

UserControl XAML:

<UserControl ...>
    <Grid>
        <TextBlock x:Name="textBlock"/>
    </Grid>
</UserControl>

UserControl Code:

public partial class TextV : UserControl
{
    public TextV()
    {
        InitializeComponent();
        MyText = "Default In Constructor";
    }

    public static readonly DependencyProperty MyTextProperty =
       DependencyProperty.Register("MyText", typeof(string), typeof(TextV),
       new PropertyMetadata("", new PropertyChangedCallback(HandleMyTextValueChanged)));

    public string MyText
    {
        get { return (string)GetValue(MyTextProperty); }
        set { SetValue(MyTextProperty, value); }
    }

    private static void HandleMyTextValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
    {
        TextV tv = d as TextV;
        if(tv != null) tv.textBlock.Text = args.NewValue.ToString();
    }
}
Copyread answered 17/8, 2010 at 21:11 Comment(0)
M
4

The value that you set in code has a higher priority than any value set in XAML.

Instead, you should override the default value in your derived type.

Mousebird answered 29/6, 2011 at 13:5 Comment(0)
E
2

I can reproduce the problem, but I have no idea what's causing it... Apparently it works if you remove the initialization from the constructor. If the default value is constant, your best option is to use it as the dependency property's default value, rather than set it in the constructor.

Anyway, what are you trying to do exactly? Couldn't it be achieved by a binding on the ViewModel?

Erma answered 17/8, 2010 at 23:21 Comment(2)
Thanks a lot! I didn't think about the initialization in the constructor. In my case the property is a time stamp and I wanted the instance to have a default value when the object was created and not when the static property registration happened. But that property is bound to a VM anyway, so now I will just initialize that in the VM. This will do for now, but still leaves me puzzled as to the difference between putting the control in the Window and putting it in the DataTemplate. By the way, binding MyText to the VM shows the same problem, if MyText is initialized in the constructor.Copyread
You should probably post your question on the MSDN forums, so that someone from MS can answer. I think this behavior might be a bugErma

© 2022 - 2024 — McMap. All rights reserved.