Как получить доступ к команде панели быстрого доступа «Добавить в инструмент быстрого доступа», если применима привязка источника

Как я могу добавить контейнер элементов быстрого доступа по умолчанию с помощью RibbonLibrary, если у меня есть связанная коллекция для него. Выдает Операция недействительна, пока используется ItemSource, а я добавляю элемент инструмента быстрого доступа из пользовательского интерфейса.

<r:Ribbon Name="ribbon">

        <r:Ribbon.QuickAccessToolBar>

            <r:RibbonQuickAccessToolBar ItemsSource ="{Binding QuickMenuItems, Mode=OneWay}">
                <r:RibbonQuickAccessToolBar.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <r:RibbonButton QuickAccessToolBarId="{Binding RibbonId}" Label="{Binding Label}" SmallImageSource="{Binding ImageUri}" Command="{Binding Command}"/>
                        </StackPanel>
                    </DataTemplate>
                </r:RibbonQuickAccessToolBar.ItemTemplate>
            </r:RibbonQuickAccessToolBar>

        </r:Ribbon.QuickAccessToolBar>

        <r:RibbonTab Header="Home">
            <r:RibbonGroup x:Name="Clipboard" ItemsSource ="{Binding MenuItems, Mode=OneWay}" >

                <r:RibbonGroup.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <r:RibbonButton QuickAccessToolBarId="{Binding RibbonId}" Label="{Binding Label}" SmallImageSource="{Binding ImageUri}" Command="{Binding Command}"/>
                        </StackPanel>
                    </DataTemplate>
                </r:RibbonGroup.ItemTemplate>

            </r:RibbonGroup>
        </r:RibbonTab>

    </r:Ribbon>


 ObservableCollection<RibbonItem> _MenuItems;
 ObservableCollection<RibbonItem> _QuickMenuItems;

 public ObservableCollection<RibbonItem> MenuItems
 {
      get { return _MenuItems; }
 }
 public ObservableCollection<RibbonItem> QuickMenuItems
 {
      get { return _QuickMenuItems; }
 }
public class RibbonItem
{
    public RibbonItem(string label, string imageUri, ICommand command, string ribbonId)
    {
        Label = label;
        ImageUri = imageUri;
        Command = command;
    }

    public string Label { get; private set; }

    public string ImageUri { get; private set; }

    public ICommand Command { get; private set; }

    public string RibbonId { get; private set; }
}

Ошибка во время

введите здесь описание изображения

введите здесь описание изображения
Если непонятно, добавьте комментарий.


person Ankush Madankar    schedule 22.07.2015    source источник


Ответы (4)


Это позволит вам добавлять элементы быстрого меню как из элемента управления ленты, так и из ViewModel. Я использовал ListBox в качестве прокси между ViewModel и RibbonQuickAccessToolBar. Когда элементы добавляются в ListBox, представление добавит их в RibbonQuickAccessToolBar.

Создайте свернутую ListBox, которая будет привязана к коллекции в ViewModel, и удалите привязку ItemsSource для RibbonQuickAccessToolBar:

<ListBox ItemsSource="{Binding QuickMenuItems, Mode=OneWay}"
            x:Name="ProxyListBox"
            Visibility="Collapsed"/>
<ribbon:Ribbon Name="ribbon">
    <ribbon:Ribbon.QuickAccessToolBar>
        <ribbon:RibbonQuickAccessToolBar x:Name="QuickAccessToolBar" DataContextChanged="QuickAccessToolBar_OnDataContextChanged">
            <ribbon:RibbonQuickAccessToolBar.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <ribbon:RibbonButton QuickAccessToolBarId="{Binding RibbonId}" Label="{Binding Label}" SmallImageSource="{Binding ImageUri}" Command="{Binding Command}"/>
                    </StackPanel>
                </DataTemplate>
            </ribbon:RibbonQuickAccessToolBar.ItemTemplate>
        </ribbon:RibbonQuickAccessToolBar>
    </ribbon:Ribbon.QuickAccessToolBar>
    <ribbon:RibbonTab Header="Home">
        <ribbon:RibbonGroup x:Name="Clipboard" ItemsSource ="{Binding MenuItems, Mode=OneWay}" >
            <ribbon:RibbonGroup.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <ribbon:RibbonButton QuickAccessToolBarId="{Binding RibbonId}" Label="{Binding Label}" SmallImageSource="{Binding ImageUri}" Command="{Binding Command}"/>
                    </StackPanel>
                </DataTemplate>
            </ribbon:RibbonGroup.ItemTemplate>
        </ribbon:RibbonGroup>
    </ribbon:RibbonTab>
</ribbon:Ribbon>

В коде программной части используйте DataContextChanged ListBox, чтобы прикрепить обработчик событий для события CollectionChanged ListBox.ItemsSource:

private void ProxyListBox_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.NewItems != null)
    {
        foreach (var newItem in e.NewItems)
        {
            QuickAccessToolBar.Items.Add(newItem);
        }
    }

    if (e.OldItems != null)
    {
        foreach (var oldItem in e.OldItems)
        {
            QuickAccessToolBar.Items.Remove(oldItem);
        }
    }
}

private void QuickAccessToolBar_OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    ((INotifyCollectionChanged)ProxyListBox.Items).CollectionChanged += ProxyListBox_CollectionChanged;
}

ViewModel такая же, как и раньше:

class RibbonViewModel
{
    ObservableCollection<RibbonItem> _MenuItems;

    ObservableCollection<RibbonItem> _QuickMenuItems;

    public ObservableCollection<RibbonItem> MenuItems
    {
        get { return _MenuItems; }
    }

    public ObservableCollection<RibbonItem> QuickMenuItems
    {
        get { return _QuickMenuItems; }
    }

    public RibbonViewModel()
    {
        _QuickMenuItems = new ObservableCollection<RibbonItem>();
        _MenuItems = new ObservableCollection<RibbonItem>();
    }

    public class RibbonItem
    {
        public RibbonItem(string label, string imageUri, ICommand command)
        {
            Label = label;
            ImageUri = imageUri;
            Command = command;
        }

        public string Label { get; private set; }

        public string ImageUri { get; private set; }

        public ICommand Command { get; private set; }

        public string RibbonId { get; private set; }
    }
}
person Glen Thomas    schedule 06.08.2015


Одним из обходных путей было бы не использовать RibbonQuickAccessToolBar.ItemsSource. Если вам нужно получать уведомления об изменениях в QuickAccessToolbar, подпишитесь на INotifyCollectionChanged из RibbonQuickAccessToolBar.Items.

   public RibbonWindow() {
        InitializeComponent();
        ((INotifyCollectionChanged)QuickAccessToolBar.Items).CollectionChanged += QuickAccessToolBar_ItemsCollectionChanged;
    }

    private void QuickAccessToolBar_ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
        switch (e.Action) {
           //Do stuff or synchronize to observableCollection
        }
    }
person Tedy Pranolo    schedule 03.08.2015

Наконец, я могу решить свою проблему с помощью кода, для которого я использую поведение прикрепления для RibbonWindow, вот решение:

public class RibbonWindowQuickAccessItemBehaviour : Behavior<RibbonWindow>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.Loaded += RibbonControl_Loaded;
        AssociatedObject.Closing += RibbonControl_Closing;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        AssociatedObject.Loaded -= RibbonControl_Loaded;
        AssociatedObject.Closing -= RibbonControl_Closing;
    }

    private void RibbonControl_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        var ribbonWindow = (RibbonWindow)sender;

        var ribbon = ribbonWindow.FindAllChildrenOfType<Microsoft.Windows.Controls.Ribbon.Ribbon>().Where(a => a.Name == "ribbon").FirstOrDefault();

        if (ribbon == null) return;

        var dataContext = ribbon.DataContext;

        if (dataContext is IRibbonMainWindowViewModel)
        {
            IRibbon windowsRibbon = (dataContext as IRibbonMainWindowViewModel).WindowRibbon;

            windowsRibbon.QuickAccessMenuItems.Clear();

            if (ribbon.QuickAccessToolBar != null && ribbon.QuickAccessToolBar.Items != null && ribbon.QuickAccessToolBar.Items.Count > 0)
            {
                foreach (var item in ribbon.QuickAccessToolBar.Items)
                {
                    if (item is RibbonButton)
                    {
                        var ribbonItem = item as RibbonButton;

                        windowsRibbon.QuickAccessMenuItems.Add
                            (new Gno.Framework.ClientShell.Ribbon.MenuItem(ribbonItem.Label,
                                ribbonItem.SmallImageSource == null ? string.Empty : ribbonItem.SmallImageSource.ToString(),
                                ribbonItem.Command));
                    }
                }
            }
        }
    }

    private void RibbonControl_Loaded(object sender, RoutedEventArgs e)
    {
        var ribbonWindow = (RibbonWindow)sender;

        var ribbon = ribbonWindow.FindAllChildrenOfType<Microsoft.Windows.Controls.Ribbon.Ribbon>().Where(a => a.Name == "ribbon").FirstOrDefault();

        if (ribbon == null) return;

        var dataContext = ribbon.DataContext;

        if (dataContext is IRibbonMainWindowViewModel)
        {
            IRibbon windowsRibbon = (dataContext as IRibbonMainWindowViewModel).WindowRibbon;

            var quickAccessMenus = windowsRibbon.QuickAccessMenuItems;

            if (quickAccessMenus != null && quickAccessMenus.Count > 0)
            {
                ribbon.QuickAccessToolBar = new RibbonQuickAccessToolBar();

                foreach (var quickMenu in windowsRibbon.QuickAccessMenuItems)
                {
                    var ribbonButton = new RibbonButton();

                    ribbonButton.Command = quickMenu.Command;
                    ribbonButton.Label = quickMenu.Header;

                    if (!string.IsNullOrEmpty(quickMenu.ImageUri))
                        ribbonButton.SmallImageSource = new BitmapImage(new Uri(quickMenu.ImageUri));

                    ribbon.QuickAccessToolBar.Items.Add(ribbonButton);
                }
            }
        }
    }
}

На самом деле это код для сохранения QuickAccessToolBarItem, поэтому необходимо привязать событие Window Close и Load.

person Ankush Madankar    schedule 07.08.2015