peter70
peter70

Reputation: 1113

How to get explicit specified properties from xaml

I have a loop with children of a grid. For every child, I want to know which properties have been specified explicitly in the XAML code. Do I have a chance to find out?

For example: I have a TextBox

<TextBox Height="150"/>

Only the property Height is given by XAML-Code. How I can find it out in the c# Code? In other words, I don't want all of the properties of the TextBox, but only those who are specified in the XAML.

Upvotes: 3

Views: 449

Answers (3)

mark.monteiro
mark.monteiro

Reputation: 2941

Based on the link provided provided in Sheridan's answer, here is the very small code snippet required to get all the properties set on an element in XAML:

MarkupWriter.GetMarkupObjectFor(element).Properties

Upvotes: 0

Sheridan
Sheridan

Reputation: 69987

This was a challenging question, but luckily for you, I like a good challenge. So initially, I found the DependencyPropertyHelper.GetValueSource method. This method takes a DependencyObject and a DependencyProperty and returns a ValueSource struct:

ValueSource valueSource = DependencyPropertyHelper.GetValueSource(SomeTextBlock, 
    TextBlock.TextWrappingProperty);

The ValueSource struct has a BaseValueSource enum property which has the following members:

enter image description here

These values relate to the list of DependencyProperty precedences and specify the different ways that a DependencyProperty value can be changed. A BaseValueSource enum instance value of Local means that the property was set locally using the SetValue method... this will also include instances where a property was set in code using the SetValue method. The Framework uses this method to set values from XAML markup.

The only problem was that we'd now have to find a collection of all of the DependencyPropertys of a particular DependencyObject so that we could call the above method on each to see if it was set by the SetValue method. I was hoping that Microsoft would have given us something to do this for us, but it appears not.

After a quick search, I found a way to do this using Reflection in the List properties of a DependencyObject? post here on StackOverflow. However, I kept looking and then came across a better method... a much better method. I found it in the Getting list of all dependency/attached properties of an Object question on the Visual Studio Forum.

If you look down that page at the answer from Zhou Yong, you can find a DependencyPropertyHelper class that he created. At first I thought 'let me just run this DependencyPropertyHelper.GetValueSource method to see what I get' and was expecting a long list of all of the DependencyPropertys of the TextBlock.

However, it turns out that what comes out of this method is exactly what you're after. It only returns the properties that have actually been set in XAML. In his code, I see a MarkupObject, a MarkupProperty and a MarkupWriter. I've not used these before, but it seems that this is actually looking at the XAML defined for the TextBlock. So in helping you, I've actually learned some new things too... +1 good question.

Bearing that in mind, I believe that you can ignore the earlier part of my answer regarding the ValueSource struct and just use that method. Let me know If you need any more help.

Upvotes: 3

Paul Sinnema
Paul Sinnema

Reputation: 2792

You could inherit the TextBox in your own code. The PropertyChanged could then be overriden and you would receive any properties changing.

public class MyTextBox : TextBox
{
    public MyTextBox()
    {
    }

    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        Console.WriteLine(string.Format("Property changed: {0} {1}", e.Property.Name, e.NewValue));

        base.OnPropertyChanged(e);
    }
}

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <local:MyTextBox x:Name="TB" Height="150"></local:MyTextBox>
</Grid>
</Window>

Unfortunatly you will also receive properties changed by styles

Here's the result of the code above

Property changed: UndoManagerInstance MS.Internal.Documents.UndoManager

Property changed: Instance System.Windows.Documents.TextEditor

Property changed: XmlnsDictionary System.Windows.Markup.XmlnsDictionary

Property changed: IWindowService WpfApplication1.MainWindow

Property changed: Name TB

Property changed: Height 150

Property changed: Background #FFFFFFFF

Property changed: BorderBrush #FFABADB3

Property changed: Foreground #FF000000

Property changed: BorderThickness 1,1,1,1

Property changed: TabNavigation None

Property changed: FocusVisualStyle

Property changed: AllowDrop True

Property changed: PanningMode VerticalFirst

Property changed: IsFlicksEnabled False

Property changed: Template System.Windows.Controls.ControlTemplate

Property changed: XmlNamespaceMaps System.Collections.Hashtable

Property changed: XmlnsDictionary System.Windows.Markup.XmlnsDictionary

Property changed: XmlNamespaceMaps System.Collections.Hashtable

Property changed: IsVisible True

Property changed: ActualWidth 509

Property changed: ActualHeight 150

Property changed: PageHeight 148

Upvotes: 0

Related Questions