views:

38

answers:

2

In my user interface I sometimes want to put titles above usercontrols.

I want to declare these titles in XAML for future localizability, so I want to keep them out of the datacontexts.

Can databinding fetch them from a property set on the root node of the usercontrol?

I have boiled the problem down to the following code example:

using System.Windows;

namespace WpfApplication12
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.Person = new Author { Name = "Guge" };

            this.DataContext = this;
        }

        public object Person { get; set; }
    }

    public class Author
    {
        public string Name { get; set; }
    }
}

And:

<Window x:Class="WpfApplication12.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication12"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <DataTemplate DataType="{x:Type local:Author}">
        <Border AutomationProperties.Name="Author" BorderThickness="1" BorderBrush="Black">
            <Label Content="{Binding Name}"/>
        </Border>
    </DataTemplate>
</Window.Resources>
<StackPanel>
    <Label x:Name="Position" Content="Author"/>
    <ContentControl x:Name="presentation" Content="{Binding Person}"/>
</StackPanel>

And the practical problem is: how can I use databinding in the content property of the "Position" Label to fetch the word "Author" from the AutomationProperties.Name property of the Border in the DataTemplate?

A: 

How about going the route over your data object:

public class Author
{
    public string Name { get; set; }
    public string TypeName { get; set; } // might be better in base class Person
}

And:

<Window.Resources>
    <DataTemplate DataType="{x:Type local:Author}">
        <Border AutomationProperties.Name="{Binding TypeName}" 
                BorderThickness="1" BorderBrush="Black">
            <Label Content="{Binding Name}"/>
        </Border>
    </DataTemplate>
</Window.Resources>
<StackPanel>
    <Label x:Name="Position" Content="{Binding ElementName=presentation, Path=DataContext.TypeName}"/>
    <ContentControl x:Name="presentation" Content="{Binding Person}"/>
</StackPanel>
bitbonk
Thanks. And I suppose setting TypeName to the contents of AutomationProperties.Name in code-behind?
Guge
There must be some place where Person.TypeName is set, yes. Generally speaking I do not like codebhind ( http://goo.gl/KyTW ). But if you use it, yes that's probably the place.
bitbonk
Your databinding expression for the TypeName doesn't work.
Guge
Of course you need to use the INotifyPropertyChanged pattern for the properties. Do you have that?
bitbonk
A: 

The solution so far is to add a string property for TypeName to the viewmodel and fill this with the contents of the AutomationProperties.Name in code-behind. And use the following binding:

<StackPanel>
    <Label x:Name="Position" Content="{Binding Person.TypeName}"/>
    <ContentControl x:Name="presentation" Content="{Binding Person}"/>
</StackPanel>

However, I still think it should be possible to do this without using the ViewModel, I hope to be able to revisit this issue when my databinding skills have improved.

Guge