Лента Microsoft WPF (выпуск за октябрь 2010 г.) - привязка к содержимому - PullRequest
1 голос
/ 22 ноября 2010

У меня есть экземпляр Microsoft Ribbon в моем приложении, и я пытаюсь связать содержимое RibbonGroup с коллекцией изображений в моей ViewModel таким образом, чтобы (а) изображение отображается как большое изображение RibbonButton и (b) когда пользователь щелкает один из элементов управления RibbonButton, соответствующее изображение устанавливается в качестве CurrentItem коллекции (в настоящее время EntityCollection).

Я пробовал различные способы, свободно основанные на следующем ...

    <DataTemplate x:Key="viewButtonTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <ribbon:RibbonButton Grid.Row="0" Label="{Binding Path=ImageType.Description}"
                                                 LargeImageSource="{Binding Path=ImageData, Converter={StaticResource BinaryJpegToImageSourceConverter}}"
                                                 Command=""/>
            <Image Grid.Row="0" MaxWidth="30" Source="{Binding Path=ImageData, Converter={StaticResource BinaryJpegToImageSourceConverter}}"/>
            <TextBlock Grid.Row="1" Text="{Binding Path=ImageType.Description}"/>
        </Grid>
    </DataTemplate>


<ribbon:RibbonGroup Header="View">
    <ListBox Name="imageList" Background="Transparent" BorderThickness="0" Focusable="True" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=Images}" ItemTemplate="{StaticResource viewButtonTemplate}" ScrollViewer.VerticalScrollBarVisibility="Hidden">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
    </ListBox>
</ribbon:RibbonGroup>

Но все безрезультатно! Я просто не могу заставить RibbonButton действовать так, как я хочу. Примечание. Дополнительный элемент управления изображением в шаблоне фактически позволяет ему работать; похоже, это связано с тем, что ListView распознает щелчок RibbonButton.

Есть предложения?

1 Ответ

5 голосов
/ 22 ноября 2010

Я реализовал приложение WPF, которое использует элемент управления ленты с шаблоном MVVM, но мой подход заключался в создании набора интерфейсов навигации, к которым я привязывал ленту.Я также использовал стили элементов ленты для управления связыванием данных, которое, как я считаю, может помочь вам добиться того, что вам нужно.

После привязки вашего элемента управления ленты к модели представления вы можете заполнить вкладки и их дочерние группы.таким образом, что изображения, которые вы хотите отобразить, будут отрисованы, а затем укажите ICommand для модели представления, которую вы хотите выполнить при выборе группы.Эта команда вызовет метод для установки текущего элемента коллекции.

Стили управления лентой:

<Window.Resources>

    <!-- RibbonMenuItem -->
    <Style TargetType="{x:Type ribbon:RibbonMenuItem}">
        <Setter Property="Header" Value="{Binding Header}" />
        <Setter Property="ImageSource" Value="{Binding Image}" />
        <Setter Property="ribbon:RibbonControlService.ToolTipTitle" Value="{Binding ToolTipTitle}" />
        <Setter Property="ribbon:RibbonControlService.ToolTipDescription" Value="{Binding ToolTipDescription}" />
        <Setter Property="ribbon:RibbonControlService.ToolTipImageSource" Value="{Binding ToolTipImage}" />
        <Setter Property="ribbon:RibbonControlService.ToolTipFooterTitle" Value="{Binding ToolTipFooterTitle}" />
        <Setter Property="ribbon:RibbonControlService.ToolTipFooterDescription" Value="{Binding ToolTipFooterDescription}" />
        <Setter Property="ribbon:RibbonControlService.ToolTipFooterImageSource" Value="{Binding ToolTipFooterImage}" />
        <Setter Property="KeyTipService.KeyTip" Value="{Binding KeyTip}" />
        <Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
        <Setter Property="Command" Value="{Binding Command}" />
        <Setter Property="IsCheckable" Value="{Binding IsCheckable}" />
        <Setter Property="IsChecked" Value="{Binding IsChecked}" />
        <Setter Property="CanUserResizeVertically" Value="{Binding IsVerticallyResizable}" />
        <Setter Property="CanUserResizeHorizontally" Value="{Binding IsHorizontallyResizable}" />
        <Setter Property="ItemsSource" Value="{Binding Items}" />

        <Style.Triggers>
            <DataTrigger Binding="{Binding Command}" Value="{x:Null}">
                <Setter Property="Command" Value="{x:Null}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding CommandParameter}" Value="{x:Null}">
                <Setter Property="CommandParameter" Value="{x:Null}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Image}" Value="{x:Null}">
                <Setter Property="ImageSource" Value="{x:Null}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding ToolTipImage}" Value="{x:Null}">
                <Setter Property="ribbon:RibbonControlService.ToolTipImageSource" Value="{x:Null}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding ToolTipFooterImage}" Value="{x:Null}">
                <Setter Property="ribbon:RibbonControlService.ToolTipFooterImageSource" Value="{x:Null}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <!-- RibbonSplitMenuItem -->
    <Style TargetType="{x:Type ribbon:RibbonSplitMenuItem}" BasedOn="{StaticResource {x:Type ribbon:RibbonMenuItem}}">
        <Setter Property="HeaderQuickAccessToolBarId" Value="{Binding Command}" />
        <Setter Property="QuickAccessToolBarId" Value="{Binding DropDownButtonData.Command}" />
        <Setter Property="HeaderKeyTip" Value="{Binding KeyTip}" />
        <Setter Property="KeyTip" Value="{Binding DropDownButtonData.KeyTip}" />
        <Setter Property="DropDownToolTipTitle" Value="{Binding DropDownButtonData.ToolTipTitle}" />
        <Setter Property="DropDownToolTipDescription" Value="{Binding DropDownButtonData.ToolTipDescription}" />
        <Setter Property="DropDownToolTipImageSource" Value="{Binding DropDownButtonData.ToolTipImage}" />
        <Setter Property="DropDownToolTipFooterTitle" Value="{Binding DropDownButtonData.ToolTipFooterTitle}" />
        <Setter Property="DropDownToolTipFooterDescription" Value="{Binding DropDownButtonData.ToolTipFooterDescription}" />
        <Setter Property="DropDownToolTipFooterImageSource" Value="{Binding DropDownButtonData.ToolTipFooterImage}" />
        <Style.Triggers>
            <DataTrigger Binding="{Binding DropDownButtonData.ToolTipImage}" Value="{x:Null}">
                <Setter Property="DropDownToolTipImageSource" Value="{x:Null}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding DropDownButtonData.ToolTipFooterImage}" Value="{x:Null}">
                <Setter Property="DropDownToolTipFooterImageSource" Value="{x:Null}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <!-- RibbonApplicationMenuItem -->
    <Style TargetType="{x:Type ribbon:RibbonApplicationMenuItem}" BasedOn="{StaticResource {x:Type ribbon:RibbonMenuItem}}">
        <Style.Triggers>
            <Trigger Property="Level" Value="Middle">
                <Setter Property="ImageSource" Value="{Binding Image}" />
                <Setter Property="KeyTipService.KeyTip" Value="{Binding KeyTip}" />
                <Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
                <Setter Property="Command" Value="{Binding Command}" />
                <Setter Property="Header" Value="{Binding Header}" />
            </Trigger>
        </Style.Triggers>
    </Style>

    <!-- RibbonApplicationSplitMenuItem -->
    <Style TargetType="{x:Type ribbon:RibbonApplicationSplitMenuItem}" BasedOn="{StaticResource {x:Type ribbon:RibbonSplitMenuItem}}" />

    <!-- RibbonTab -->
    <Style TargetType="{x:Type ribbon:RibbonTab}">
        <Setter Property="Header" Value="{Binding Header}" />
        <Setter Property="ItemsSource" Value="{Binding Groups}" />
    </Style>

    <!-- RibbonGroupItem -->
    <Style TargetType="{x:Type ribbon:RibbonButton}" x:Key="RibbonGroupItemButton">
        <Setter Property="Label" Value="{Binding Label}" />
        <Setter Property="LargeImageSource" Value="{Binding LargeImage}" />
        <Setter Property="SmallImageSource" Value="{Binding SmallImage}" />
        <Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
        <Setter Property="Command" Value="{Binding Command}" />

        <Style.Triggers>
            <DataTrigger Binding="{Binding LargeImage}" Value="{x:Null}">
                <Setter Property="LargeImageSource" Value="{x:Null}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding SmallImage}" Value="{x:Null}">
                <Setter Property="SmallImageSource" Value="{x:Null}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <DataTemplate DataType="{x:Type ribbon:RibbonControl}"  x:Key="RibbonGroupItemTemplate">
        <ribbon:RibbonButton Style="{StaticResource RibbonGroupItemButton}" />
    </DataTemplate>

    <!-- RibbonGroup -->
    <Style TargetType="{x:Type ribbon:RibbonGroup}">
        <Setter Property="Header" Value="{Binding Header}" />
        <Setter Property="ItemsSource" Value="{Binding Items}" />
        <Setter Property="ItemTemplate" Value="{StaticResource RibbonGroupItemTemplate}" />
    </Style>

</Window.Resources>

Свойства, предоставляемые моделью представления (привязка данных):

#region MenuItems
/// <summary>
/// Gets the application menu items.
/// </summary>
/// <value>
/// A <see cref="SelectableObservableCollection{IMenuItem}"/> that contains 
/// the application menu items. The default value is an <i>empty</i> collection.
/// </value>
public SelectableObservableCollection<IMenuItem> MenuItems
{
    get
    {
        if (_viewModelMenuItems == null)
        {
            _viewModelMenuItems = new SelectableObservableCollection<IMenuItem>();
        }
        return _viewModelMenuItems;
    }
}
private SelectableObservableCollection<IMenuItem> _viewModelMenuItems;
#endregion

#region Tabs
/// <summary>
/// Gets the application navigation tabs.
/// </summary>
/// <value>
/// A <see cref="SelectableObservableCollection{INavigationTab}"/> that contains 
/// the application navigation tabs. The default value is an <i>empty</i> collection.
/// </value>
public SelectableObservableCollection<INavigationTab> Tabs
{
    get
    {
        if (_viewModelTabs == null)
        {
            _viewModelTabs = new SelectableObservableCollection<INavigationTab>();
        }
        return _viewModelTabs;
    }
}
private SelectableObservableCollection<INavigationTab> _viewModelTabs;
#endregion

Вид (лента XAML):

<ribbon:Ribbon Grid.Row="0" ItemsSource="{Binding Path=Tabs}">

    <ribbon:Ribbon.ApplicationMenu>
        <ribbon:RibbonApplicationMenu 
            Margin="0, 5, 0, 0"
            LargeImageSource="/MyApp;component/Resources/Images/ApplicationMenu.png" 
            SmallImageSource="/MyApp;component/Resources/Icons/ApplicationMenu.png" 
            ItemsSource="{Binding Path=MenuItems}" 
        >
            <ribbon:RibbonApplicationMenu.FooterPaneContent>
                <DockPanel LastChildFill="False">
                    <ribbon:RibbonButton 
                        DockPanel.Dock="Right" Margin="2" BorderBrush="#B8114EAF" 
                        Command="{Binding Path=Shutdown}"
                        Label="Exit" ToolTipTitle="Quit application" KeyTip="X" 
                        SmallImageSource="/MyApp;component/Resources/Icons/Exit.png" />
                </DockPanel>
            </ribbon:RibbonApplicationMenu.FooterPaneContent>

        </ribbon:RibbonApplicationMenu>
    </ribbon:Ribbon.ApplicationMenu>

</ribbon:Ribbon>

Интерфейсы навигации:

public interface IMenuItem : ICloneable, INotifyPropertyChanged, INotifyPropertyChanging
{
    #region Command
    /// <summary>
    /// Gets or sets the command associated with the menu item.
    /// </summary>
    /// <value>
    /// The <see cref="ISurrogateCommand"/> associated with the menu item.
    /// </value>
    ISurrogateCommand Command
    {
        get;
        set;
    }
    #endregion

    #region CommandParameter
    /// <summary>
    /// Gets or sets the parameter to pass to the command associated with the menu item.
    /// </summary>
    /// <value>
    /// The parameter to pass to the <see cref="Command"/> associated with the menu item.
    /// </value>
    object CommandParameter
    {
        get;
        set;
    }
    #endregion

    #region Header
    /// <summary>
    /// Gets or sets the item that labels the menu item.
    /// </summary>
    /// <value>
    /// The item that labels the menu item.
    /// </value>
    object Header
    {
        get;
        set;
    }
    #endregion

    #region Image
    /// <summary>
    /// Gets or sets the image that is displayed on the menu item.
    /// </summary>
    /// <value>
    /// The <see cref="ImageSource"/> that is displayed on the menu item.
    /// </value>
    ImageSource Image
    {
        get;
        set;
    }
    #endregion

    #region IsCheckable
    /// <summary>
    /// Gets or sets a value that indicates whether the menu item can be checked.
    /// </summary>
    /// <value>
    /// <see langword="true"/> if the menu item can be checked; otherwise, <see langword="false"/>.
    /// </value>
    bool IsCheckable
    {
        get;
        set;
    }
    #endregion

    #region IsChecked
    /// <summary>
    /// Gets or sets a value that indicates whether the menu item is checked.
    /// </summary>
    /// <value>
    /// <see langword="true"/> if the menu item is checked; otherwise, <see langword="false"/>.
    /// </value>
    bool IsChecked
    {
        get;
        set;
    }
    #endregion

    #region IsHorizontallyResizable
    /// <summary>
    /// Gets or sets a value that indicates whether the menu item can be resized horizontally.
    /// </summary>
    /// <value>
    /// <see langword="true"/> if the menu item can be resized horizontally; otherwise, <see langword="false"/>.
    /// </value>
    bool IsHorizontallyResizable
    {
        get;
        set;
    }
    #endregion

    #region IsVerticallyResizable
    /// <summary>
    /// Gets or sets a value that indicates whether the menu item can be resized vertically.
    /// </summary>
    /// <value>
    /// <see langword="true"/> if the menu item can be resized vertically; otherwise, <see langword="false"/>.
    /// </value>
    bool IsVerticallyResizable
    {
        get;
        set;
    }
    #endregion

    #region Items
    /// <summary>
    /// Gets the child menu items for the menu item.
    /// </summary>
    /// <value>
    /// A <see cref="SelectableObservableCollection{IMenuItem}"/> collection that contains the child menu items for the menu item.
    /// </value>
    SelectableObservableCollection<IMenuItem> Items
    {
        get;
    }
    #endregion

    #region KeyTip
    /// <summary>
    /// Gets or sets the text to use for the menu item key tip.
    /// </summary>
    /// <value>
    /// The text to use for the menu item key tip.
    /// </value>
    string KeyTip
    {
        get;
        set;
    }
    #endregion

    #region ToolTipDescription
    /// <summary>
    /// Gets or sets the description for the menu item tooltip.
    /// </summary>
    /// <value>
    /// The description for the menu item tooltip.
    /// </value>
    string ToolTipDescription
    {
        get;
        set;
    }
    #endregion

    #region ToolTipFooterDescription
    /// <summary>
    /// Gets or sets the description for the menu item tooltip footer.
    /// </summary>
    /// <value>
    /// The description for the menu item tooltip footer.
    /// </value>
    string ToolTipFooterDescription
    {
        get;
        set;
    }
    #endregion

    #region ToolTipFooterImage
    /// <summary>
    /// Gets or sets the image for the menu item tooltip footer.
    /// </summary>
    /// <value>
    /// The <see cref="ImageSource"/> for the menu item tooltip footer.
    /// </value>
    ImageSource ToolTipFooterImage
    {
        get;
        set;
    }
    #endregion

    #region ToolTipFooterTitle
    /// <summary>
    /// Gets or sets the title for the menu item tooltip footer.
    /// </summary>
    /// <value>
    /// The title for the menu item tooltip footer.
    /// </value>
    string ToolTipFooterTitle
    {
        get;
        set;
    }
    #endregion

    #region ToolTipImage
    /// <summary>
    /// Gets or sets the image for the menu item tooltip.
    /// </summary>
    /// <value>
    /// The <see cref="ImageSource"/> for the menu item tooltip.
    /// </value>
    ImageSource ToolTipImage
    {
        get;
        set;
    }
    #endregion

    #region ToolTipTitle
    /// <summary>
    /// Gets or sets the title for the menu item tooltip.
    /// </summary>
    /// <value>
    /// The title for the menu item tooltip.
    /// </value>
    string ToolTipTitle
    {
        get;
        set;
    }
    #endregion
}

public interface INavigationTab : ICloneable, INotifyPropertyChanged, INotifyPropertyChanging
{
    #region Groups
    /// <summary>
    /// Gets the groups for the navigation tab.
    /// </summary>
    /// <value>
    /// A <see cref="SelectableObservableCollection{INavigationTabGroup}"/> collection that contains 
    /// the navigation groups for the navigation tab.
    /// </value>
    SelectableObservableCollection<INavigationTabGroup> Groups
    {
        get;
    }
    #endregion

    #region Header
    /// <summary>
    /// Gets or sets the item that labels the navigation tab.
    /// </summary>
    /// <value>
    /// The item that labels the navigation tab.
    /// </value>
    object Header
    {
        get;
        set;
    }
    #endregion
}

public interface INavigationTabGroup : ICloneable, INotifyPropertyChanged, INotifyPropertyChanging
{
    #region Header
    /// <summary>
    /// Gets or sets the item that labels the navigation tab group.
    /// </summary>
    /// <value>
    /// The item that labels the navigation tab group.
    /// </value>
    object Header
    {
        get;
        set;
    }
    #endregion

    #region Items
    /// <summary>
    /// Gets the items for the navigation tab group.
    /// </summary>
    /// <value>
    /// A <see cref="SelectableObservableCollection{INavigationTabGroupItem}"/> collection that contains 
    /// the navigation items for the navigation tab group.
    /// </value>
    SelectableObservableCollection<INavigationTabGroupItem> Items
    {
        get;
    }
    #endregion
}

public interface INavigationTabGroupItem : ICloneable, INotifyPropertyChanged, INotifyPropertyChanging
{
    #region Command
    /// <summary>
    /// Gets or sets the command associated with the navigation tab group item.
    /// </summary>
    /// <value>
    /// The <see cref="ISurrogateCommand"/> associated with the navigation tab group item.
    /// </value>
    ISurrogateCommand Command
    {
        get;
        set;
    }
    #endregion

    #region CommandParameter
    /// <summary>
    /// Gets or sets the parameter to pass to the command associated with the navigation tab group item.
    /// </summary>
    /// <value>
    /// The parameter to pass to the <see cref="Command"/> associated with the navigation tab group item.
    /// </value>
    object CommandParameter
    {
        get;
        set;
    }
    #endregion

    #region Label
    /// <summary>
    /// Gets or sets the item that labels the navigation tab group item.
    /// </summary>
    /// <value>
    /// The item that labels the navigation tab group item.
    /// </value>
    object Label
    {
        get;
        set;
    }
    #endregion

    #region LargeImage
    /// <summary>
    /// Gets or sets the large image that is displayed by the navigation tab group item.
    /// </summary>
    /// <value>
    /// The <see cref="ImageSource"/> that represents the large image that is displayed 
    /// by the navigation tab group item.
    /// </value>
    ImageSource LargeImage
    {
        get;
        set;
    }
    #endregion

    #region SmallImage
    /// <summary>
    /// Gets or sets the small image that is displayed by the navigation tab group item.
    /// </summary>
    /// <value>
    /// The <see cref="ImageSource"/> that represents the small image that is displayed 
    /// by the navigation tab group item.
    /// </value>
    ImageSource SmallImage
    {
        get;
        set;
    }
    #endregion
}

Вот пример модели представления, заполняющей ее коллекцию вкладок:

private void AddTabs()
{
    INavigationTab homeTab              = new NavigationTab(Properties.Resources.Shell_Tab_Home_Header);

    INavigationTabGroup generalGroup    = new NavigationTabGroup(Properties.Resources.Shell_TabGroup_General_Header);
    generalGroup.Items.Add(
        new NavigationTabGroupItem
        {
            Label               = Properties.Resources.Shell_StartPage_Header,
            LargeImage          = GetImage("/MyApp;component/Resources/Images/Home.png"),
            CommandParameter    = this,
            Command             = this.DisplayStartPage
        }
    );
    generalGroup.Items.Add(
        new NavigationTabGroupItem
        {
            Label       = Properties.Resources.Shell_Settings_Header,
            SmallImage  = GetImage("/MyApp;component/Resources/Icons/Settings.png")
        }
    );
    generalGroup.Items.Add(
        new NavigationTabGroupItem
        {
            Label       = Properties.Resources.Shell_UserInformation_Header,
            SmallImage  = GetImage("/MyApp;component/Resources/Icons/UserInformation.png")
        }
    );
    generalGroup.Items.Add(
        new NavigationTabGroupItem
        {
            Label       = Properties.Resources.Shell_About_Header,
            SmallImage  = GetImage("/MyApp;component/Resources/Icons/About.png"),
            Command     = this.AboutApplication
        }
    );

    homeTab.Groups.Add(generalGroup);

    this.Tabs.Add(homeTab);
}

Кроме того, у меня изначально были некоторые проблемы с привязкой источников изображений, но я нашелРешение с помощью Freeze.Вот пример:

// Build navigation tab
this.Tab    = new NavigationTab(Properties.Resources.Module_Tab_Header);

var administrationImage = GetImage("/MyApp;component/Resources/Images/Administration.png");
administrationImage.Freeze();

INavigationTabGroup administrationGroup = new NavigationTabGroup(Properties.Resources.Module_TabGroup_Administration_Header);
administrationGroup.Items.Add(
    new NavigationTabGroupItem
    {
        Label               = Properties.Resources.Module_StartPage_Header,
        LargeImage          = administrationImage
    }
);

/// <summary>
/// Gets an image resource in the assembly for the specified path.
/// </summary>
/// <param name="path">The relative path to the image resource.</param>
/// <returns>
/// The <see cref="System.Windows.Media.ImageSource"/> located at the specified <paramref name="path"/>.
/// </returns>
/// <example>
/// Path: <i>/MyAssembly;component/Resources/Icons/MyIcon.png</i>
/// </example>
protected static System.Windows.Media.ImageSource GetImage(string path)
{
    return new System.Windows.Media.Imaging.BitmapImage(
            new Uri(String.Format(null, "pack://application:,,,{0}", path))
    );
}

Надеюсь, это поможет вам решить проблемы с переплетом.

...