Próbowałem przy użyciu CompositeCollection
jak sugerował Kent Boogaart, ale nie mogłem pracować z powodu bug in wpf nie pozwalając użyć RelativeSource wiążącej w CollectionContainer
.
Rozwiązanie użyłem jest mieć RecentFiles
we własnym podmenu związany z Kolekcji poprzez własnością ItemsSource
.
Naprawdę chciałem mieć listę w menu „Plik”, ale myślę, że jest to kolejna najlepsza rzecz ...
Edit
Zainspirowany this article I zbudował zwyczaj i bardziej ogólnie MenuItemList
:
public class MenuItemList : Separator {
#region Private Members
private MenuItem m_Parent;
private List<MenuItem> m_InsertedMenuItems;
#endregion
public MenuItemList() {
Loaded += (s, e) => HookFileMenu();
}
private void HookFileMenu() {
m_Parent = Parent as MenuItem;
if (m_Parent == null) {
throw new InvalidOperationException("Parent must be a MenuItem");
}
if (ParentMenuItem == m_Parent) {
return;
}
if (ParentMenuItem != null) {
ParentMenuItem.SubmenuOpened -= _FileMenu_SubmenuOpened;
}
ParentMenuItem = m_Parent;
ParentMenuItem.SubmenuOpened += _FileMenu_SubmenuOpened;
}
private void _FileMenu_SubmenuOpened(object sender, RoutedEventArgs e) {
DataBind();
}
#region Properties
public MenuItem ParentMenuItem { get; private set; }
#region ItemsSource
/// <summary>
/// ItemsSource Dependency Property
/// </summary>
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(MenuItemList),
new FrameworkPropertyMetadata(null,
new PropertyChangedCallback(OnItemsSourceChanged)));
/// <summary>
/// Gets or sets a collection used to generate the content of the <see cref="MenuItemList"/>. This is a dependency property.
/// </summary>
public IEnumerable ItemsSource {
get { return (IEnumerable) GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
/// <summary>
/// Handles changes to the ItemsSource property.
/// </summary>
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
((MenuItemList) d).OnItemsSourceChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the ItemsSource property.
/// </summary>
protected virtual void OnItemsSourceChanged(DependencyPropertyChangedEventArgs e) {
DataBind();
}
#endregion
#region ItemContainerStyle
/// <summary>
/// ItemsContainerStyle Dependency Property
/// </summary>
public static readonly DependencyProperty ItemContainerStyleProperty =
DependencyProperty.Register("ItemContainerStyle", typeof(Style), typeof(MenuItemList),
new FrameworkPropertyMetadata((Style) null));
/// <summary>
/// Gets or sets the <see cref="System.Windows.Style"/> that is applied to the container element generated for each item. This is a dependency property.
/// </summary>
public Style ItemContainerStyle {
get { return (Style) GetValue(ItemContainerStyleProperty); }
set { SetValue(ItemContainerStyleProperty, value); }
}
#endregion
#endregion
private void DataBind() {
RemoveMenuItems();
InsertMenuItems();
}
private void RemoveMenuItems() {
if (m_InsertedMenuItems != null) {
foreach (var menuItem in m_InsertedMenuItems) {
ParentMenuItem.Items.Remove(menuItem);
}
}
}
private void InsertMenuItems() {
if (ItemsSource == null) {
return;
}
if (ParentMenuItem != null) {
m_InsertedMenuItems = new List<MenuItem>();
int iMenuItem = ParentMenuItem.Items.IndexOf(this);
foreach (var item in ItemsSource) {
var menuItem = new MenuItem();
menuItem.DataContext = item;
menuItem.Style = ItemContainerStyle;
ParentMenuItem.Items.Insert(++iMenuItem, menuItem);
m_InsertedMenuItems.Add(menuItem);
}
}
}
}
to dalekie od doskonałości, ale to działa na mnie. Możesz go skomentować ...
W tym artykule na blogu pokazano, jak tworzyć menu oparte na danych: http://weblogs.asp.net/okloeten/archive/2007/11/14/5149692.aspx –