views:

801

answers:

3

I have a UserControl called SmartForm which has a DependencyProperty called Status.

In my Window1.xaml, I have the element <local:SmartForm Status="Ready"/>.

I would think then in the constructor of the SmartForm object, that Status would equal "Ready" but instead it equals null.

Why is then the value of the Status property NULL in the constructor of SmartForm?

If not in the UserControl constructor, when do I have access to the value, then?

Window1.xaml:

<Window x:Class="TestPropertyDefine23282.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestPropertyDefine23282"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <local:SmartForm Status="Ready"/>
    </Grid>
</Window>

SmartForm.xaml:

<UserControl x:Class="TestPropertyDefine23282.SmartForm"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <Grid>
        <TextBlock x:Name="TestingMessage"/>
    </Grid>
</UserControl>

SmartForm.xaml.cs:

using System.Windows;
using System.Windows.Controls;

namespace TestPropertyDefine23282
{
    public partial class SmartForm : UserControl
    {
        public SmartForm()
        {
            InitializeComponent();

            TestingMessage.Text = Status; //WHY IS STATUS NOT YET SET HERE?

        }

        #region DependencyProperty: Status
        public string Status
        {
            get
            {
                return (string)GetValue(StatusProperty);
            }
            set
            {
                SetValue(StatusProperty, value);
            }
        }

        public static readonly DependencyProperty StatusProperty =
            DependencyProperty.Register("Status", typeof(string), typeof(SmartForm),
            new FrameworkPropertyMetadata());
        #endregion

    }
}
+2  A: 

You can set that testing message as:

...
    public static readonly DependencyProperty StatusProperty = 
        DependencyProperty.Register("Status", typeof(string), typeof(SmartForm),
        new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.None,
            new PropertyChangedCallback(OnStatusChanged)));

    public static void OnStatusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        ((SmartForm)d).TestingMessage.Text = e.NewValue.ToString();
    }
...

Or as:

<UserControl 
x:Class="TestPropertyDefine23282.SmartForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestPropertyDefine23282"
Height="300" Width="300"
>
<Grid>
    <TextBlock
        x:Name="TestingMessage"
        Text="{Binding Path=Status, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:SmartForm}}}"
        />
</Grid>
</UserControl>
Stanislav Kniazev
The xaml method is better, you won't have to worry about anyone catching and handling the preview property changed event outside of the control and it's cleaner if you're going to set this up for multiple DPs.
Bryan Anderson
+2  A: 
<local:SmartForm Status="Ready"/>

Translates to:

SmartForm f = new SmartForm();
f.Status = Status.Ready;

You will have access to that value when the setter is called.

siz
A: 

This is kind of tertiary, but why do you need this setter at all?

<UserControl x:Class="TestPropertyDefine23282.SmartForm"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="Control"
    Height="300" Width="300">
    <Grid>
        <TextBlock Text="{Binding Path=Status, ElementName=Control}" />
    </Grid>
</UserControl>
Paul Betts