If I have this:
<Grid xmlns:local="clr-namespace:xaml_collections">
<StackPanel>
<StackPanel.DataContext>
<local:AComposite>
<local:AComposite.TheChildren>
<Rectangle
Height="85"
Width="85"
Fill="Red"
x:Name="foobar"
/>
</local:AComposite.TheChildren>
</local:AComposite>
</StackPanel.DataContext>
<TextBlock DataContext="{Binding TheChildren[0]}">
<Run Text="{Binding Height}"></Run>
</TextBlock>
<TextBlock DataContext="{Binding ChildrenByName[foobar]}">
<Run Text="{Binding Height}"></Run>
</TextBlock>
</StackPanel>
</Grid>
and this:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Shapes;
using System.Collections.Specialized;
namespace xaml_collections
{
public class AComposite : FrameworkElement
{
public AComposite()
{
if (_TheChildren != null && _TheChildren is ObservableCollection<Rectangle>)
{
((ObservableCollection<Rectangle>)_TheChildren)
.CollectionChanged += AComposite_CollectionChanged;
}
}
void AComposite_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e != null && e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null)
{
foreach (var anItem in e.NewItems)
{
if (anItem is FrameworkElement)
{
FrameworkElement theFrameworkElementItem = (FrameworkElement)anItem;
_ChildrenByName.Add(theFrameworkElementItem.Name, theFrameworkElementItem);
}
}
}
}
private Dictionary<String,FrameworkElement> _ChildrenByName = new Dictionary<String,FrameworkElement>();
public Dictionary<String,FrameworkElement> ChildrenByName
{
get
{
return _ChildrenByName;
}
private set { }
}
private IList _TheChildren = new ObservableCollection<Rectangle>();
public IList TheChildren
{
get
{
return _TheChildren;
}
private set { }
}
}
}
I can see the value of Height which is 85 in the TextBlock
for the TextBlock
bound to Children[0]
at design time. But I can only see the value of ChildrenByName[foobar]
. Height at run time. Is there any way to keep these collections synchronized during design time as well?
EDIT
This seems to work and thanks to Nick Miller. The lesson here is suppose is don't try to create derivative collections. Use properties that don't copy the collection, but just refer to it.
public Dictionary<String,FrameworkElement> ByName
{
get
{
return
this.Children.AsQueryable().Cast<FrameworkElement>()
.ToDictionary( element => element.Tag.ToString() );
}
}
And things like this:
public List<FrameworkElement> Top3
{
get
{
return
this.Children.AsQueryable().Cast<FramworkElement>().
OrderByDescending( element => element.Height )
.Take(3).ToList();
}
}