【问题标题】:Microsoft WPF Ribbon (Oct/2010 release) - Binding to contentMicrosoft WPF 功能区(2010 年 10 月版)- 绑定到内容
【发布时间】:2010-11-22 17:15:57
【问题描述】:

我的应用程序中有一个Microsoft Ribbon 的实例,我正在尝试将 RibbonGroup 的内容绑定到我的 ViewModel 中的图像集合,以便 (a) 图像显示为大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 的点击有关。

有什么建议吗?

【问题讨论】:

    标签: .net wpf ribbon ribbon-control


    【解决方案1】:

    我已经实现了一个 WPF 应用程序,它使用带有 MVVM 模式的 Ribbon 控件,但我的方法是创建一组我将 Ribbon 绑定到的导航界面。我还利用功能区元素的样式来控制数据绑定,我相信这可以帮助您完成您所追求的目标。

    将您的 Ribbon 控件绑定到视图模型后,您可以填充选项卡及其子组,以便呈现您要显示的图像,然后在视图模型上指定您希望执行的 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
    }
    

    以下是视图模型填充其 Tabs 集合的示例:

    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))
        );
    }
    

    希望这可以帮助您解决绑定问题。

    【讨论】:

    • 虽然这是一个很棒的答案 (+1),但我不确定它是否符合我的要求。就我而言,我有一组图像,我想在功能区上的按钮中显示这些图像,在窗口的主要区域中,我会显示其中一个图像。当用户单击其中一个按钮时,我希望所选图像显示在主窗口中。我不知道在任何给定时间会有多少图像,并且(目前)我没有使用 ICommand 来执行此操作。我只需要单击按钮即可被 ListView 控件识别,以便它以与仅显示图像相同的方式进行选择。
    猜你喜欢
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多