C# – How to access x:Name-property in code – for non FrameworkElement objects

cnetwpfxaml

Similar to another question, I would like to access the x:Name property of an object through code, tough in this case the object in question is not a FrameworkElement and thus does not have a Name property. I do not have access to the member variable either.

In my situation, I have a ListView with named columns and would like to extend the ListView class so that it persists the column layout. For this functionality I need named columns, and it would make sense to me to re-use the x:Name property I need to set anyway for other reasons, instead of adding an attached "ColumnName" property for example.

My current "solution":

<GridViewColumn Header="X" localControls:ExtendedListView.ColumnName="iconColumn" />

Desired:

<GridViewColumn Header="X" x:Name="iconColumn" />

So is it possible to get the "x:Name" value somehow?

Best Answer

See the answers by IanG in the following thread:
How to read the x:Name property from XAML code in the code-behind

Unfortunately, that's not quite what x:Name does. x:Name isn't technically a property - it's a Xaml directive. In the context of a .NET WPF application, x:Name means this:

"I want to be able to have access to this object via a field of this name. Also, if this type happens to have a name property, please set it to that name."

It's that second part that you need, and unfortunately that second part doesn't apply to ModelUIElement3D, because that type doesn't have a property to represent the name. So in effect, all it means is "I want to be able to have access to this object via a field of this name." And that's all.

So, all x:Name does is that it gives you access to this object by creating a field with that specific name. If you want to get the x:Name of it, you'll have to iterate all your fields and see if the field is the object you're looking for, and in that case, return the field name.

He does present a method to do this in the code behind file, although I think your current approach with an attached property is a much better solution

public string GetName(GridViewColumn column)
{
    var findMatch = from field in this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                    let fieldValue = field.GetValue(this)
                    where fieldValue == column
                    select field.Name;

    return findMatch.FirstOrDefault();
}