views:

216

answers:

2

I have a problem, and I have not found the solution yet. I woud like to create a base custom control and use it in another custom control. The base control works fine when I use it in a window, but when I use it in the other custom control, the binding does not work.

What's wrong with my code?

Code:

Model:

public class ElementModel
{
    public string Name { get; set; }
    public string FullName { get; set; }
}

The base control:

public class ListControl : Control
{        
    static ListControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ListControl), new FrameworkPropertyMetadata(typeof(ListControl)));
    }

    public ListControl()
    {
        SetValue(ElementListProperty, new List<ElementModel>());
    }

    public static readonly DependencyProperty ElementListProperty =
        DependencyProperty.Register(
        "ElementList", 
        typeof(List<ElementModel>), 
        typeof(ListControl),
        new FrameworkPropertyMetadata(new List<ElementModel>())
      );

    public List<ElementModel> ElementList
    {
        get { return (List<ElementModel>)GetValue(ElementListProperty); }
        set { SetValue(ElementListProperty, value); }
    }
}

The Wrapper Control:

public class ListWrapper : Control
{
    static ListWrapper()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ListWrapper), new FrameworkPropertyMetadata(typeof(ListWrapper)));
    }

    public ListWrapper()
    {
        SetValue(EMListProperty, new List<ElementModel>());
    }

    public static readonly DependencyProperty EMListProperty =
       DependencyProperty.Register(
       "EMList",
       typeof(List<ElementModel>),
       typeof(ListWrapper),
       new FrameworkPropertyMetadata(new List<ElementModel>())
     );

    public List<ElementModel> EMList
    {
        get { return (List<ElementModel>)GetValue(EMListProperty); }
        set { SetValue(EMListProperty, value); }
    }
}

File Generic.xaml:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UIControl">

<Style TargetType="{x:Type local:ListControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ListControl}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">

                    <ListBox ItemsSource="{TemplateBinding ElementList}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <StackPanel>
                                    <Label Content="Name:"/>
                                    <TextBlock Text="{Binding Path=Name}" />
                                    <Label Content="Full name:"/>
                                    <TextBlock Text="{Binding Path=FullName}" />
                                </StackPanel>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type local:ListWrapper}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ListWrapper}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">

                    <local:ListControl ElementList="{TemplateBinding EMList}" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

If I put the controls in the window and binding properties, than the ListControl works fine and shows the elements, but the WrapperList does not.

<Window x:Class="MainApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="clr-namespace:UIControl;assembly=UIControl"
Title="Window1" Height="304" Width="628">
<Grid>
    <ui:ListControl x:Name="listCtr" ElementList="{Binding Path=EList}" HorizontalAlignment="Left" Width="300" />
    <ui:ListWrapper x:Name="listWrp" EMList="{Binding Path=EList}" HorizontalAlignment="Right" Width="300"  Background="Gray"/>
</Grid>

And the test data injection:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        DataContext = this;
    }

    List<ElementModel> elist = null;
    public List<ElementModel> EList
    {
        get
        {
            if (elist == null)
            {
                elist = new List<ElementModel>();
                ElementModel em = new ElementModel() { Name = "Apple", FullName = "Red Apple" };
                elist.Add(em);

                em = new ElementModel() { Name = "Pineapple", FullName = "Yellow Pineapple" };
                elist.Add(em);
            }
            return elist;
        }
    }
}

Project archive

A: 

I couldn't find anywhere where you are setting the binding context:

http://msdn.microsoft.com/en-us/library/ms752347.aspx

Burt
I appended the question with sample data initialization. I have no permission to put in the question a print screen, but the window1 left side control has elements, but right side has not.
josika
A: 

I don’t know why, but if I should wrap this list of element (List) into new collection type (example ElementCollection : ObservalbeCollection) and use this collection type in the dependency property, it works fine...

public static readonly DependencyProperty EMListProperty =
   DependencyProperty.Register(
   "EMList",
   typeof(ElementCollection),
   typeof(ListWrapper),
   new FrameworkPropertyMetadata(new ElementCollection())
 );

public ElementCollection EMList
{
    get { return (ElementCollection)GetValue(EMListProperty); }
    set { SetValue(EMListProperty, value); }
}
josika