简体   繁体   中英

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.

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:

在此处输入图片说明

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 DependencyProperty s 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 DependencyProperty s 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.

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

根据 Sheridan's answer 中提供的链接,这里是获取 XAML 中元素上设置的所有属性所需的非常小的代码片段:

MarkupWriter.GetMarkupObjectFor(element).Properties

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM