Tôi đã thử sử dụng CompositeCollection
như đề xuất của Kent Boogaart, nhưng tôi không thể làm cho nó hoạt động vì bug in wpf không cho phép sử dụng liên kết RelativeSource trong CollectionContainer
.
Giải pháp tôi đã sử dụng là có RecentFiles
trong menu phụ riêng của nó được liên kết với Bộ sưu tập qua thuộc tính ItemsSource
.
Tôi thực sự muốn có danh sách trong menu 'File' nhưng tôi đoán đây là điều tốt nhất tiếp theo ...
Sửa
Lấy cảm hứng từ this article tôi đã xây dựng một phong tục và tổng quát hơn 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);
}
}
}
}
Nó hoàn hảo nhưng hoàn toàn phù hợp với tôi. Hãy bình luận về nó ...
Nguồn
2009-09-09 20:21:38
Bài viết trên blog này cho biết cách tạo menu theo hướng dữ liệu: http://weblogs.asp.net/okloeten/archive/2007/11/14/5149692.aspx –