WPF: Cannot set Name attribute value errror

When writing a custom user control you might at some point be tempted to use it as an item container. If you then try to name the nested control you will get the following error:

Cannot set Name attribute value 'myControl' on element 'SomeControl'. 'SomeControl' is under the scope of element 'ContentPanel', which already had a name registered when it was defined in another scope.

This is unfortunately a common problem caused solely by the XAML parser.

The easiest solution to overcome this is by constructing the control yourself. I did this by defining my XAML in a resource dictionary and then writing the lines required to load it at runtime. The only downside in this approach is that no designer preview is available.

Here are the 3 easy steps to write a simple container with a title on top:

1. Add a new class (ContentPanel.cs) and a Resource Dictionary (ContentPanel.xaml) to your WPF project.

2. Then write your XAML into the dictionary defining the style for your control:


<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyNamespace">
    <Style TargetType="{x:Type local:ContentPanel}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ContentPanel}">
                    <Grid Background="Transparent">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="18"/>
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Border Grid.Row="0" Background="#FF6C79A2" 
CornerRadius="4 4 0 0" Padding="5 3 5 3">
                            <TextBlock VerticalAlignment="Center" Foreground="White" 
Text="{Binding Path=Title, RelativeSource={RelativeSource FindAncestor, 
AncestorType={x:Type local:ContentPanel}}}"/>
                        </Border>
                        <ContentPresenter Grid.Row="1"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

3. Finally edit the class so that it inherits from the UserControl class and add a initialize method that will be called by the constructor to load the XAML from the resource dictionary:

    public class ContentPanel: UserControl
    {
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(ContentPanel), 
new UIPropertyMetadata(""));
        public ContentPanel()
        {
            Initialize();
        }
        private void Initialize()
        {
            ResourceDictionary resources = new ResourceDictionary();
            resources.Source = new Uri("/MyAssemblyName;component/ContentPanel.xaml", 
UriKind.RelativeOrAbsolute);
            this.Resources = resources;
        }
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }
    }

Supporting WPF Binging Without the WindowsBase Library

WPF Bindings provide a powerful way to link your data with the user interface. But what can you do to keep your data classes independent from the WPF framework?

There are a couple of ways to support WPF binding. For none-UI classes the best option is to implement the INotifyPropertyChanged and INotifyCollectionChanged interfaces. Implementing them explicitly keeps the interface of your data classes clean and all the WPF functionality available only for those classes that support it.

private event PropertyChangedEventHandler PropertyChanged;


protected void OnPropertyChanged(string name)
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(name));
}
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
    add { PropertyChanged += value; }
    remove { PropertyChanged -= value; }
}

Unfortunately in .NET 3.5 both the interfaces are a part of the WindowsBase WPF library, so it is not possible to support bindings without referencing to it. This also means all the assemblies that need to take advantage of your data classes need to reference the library.

It made me very happy to read in Jamie Rodriguez’s blog that in .NET 4.0 the notify interfaces have been type forwarded to System.dll! I could also confirm this using Visual Studio 2010 Beta 2. Hurray!

Ps. According to the Data Binding Performance article on MSDN, the notify interfaces provide a slightly better performance compared to using XXXChanged events.