多项选择

Selection of multiple items

我正在使用 RibbonControlsLibrary、WPF 和 VS2015,我需要对多个 RibbonGallery 的选择执行操作。跟着图方便理解。

What I've done

As I want you to

遵循已完成的代码:

<r:RibbonWindow.Resources>
     <DataTemplate
            x:Key="tableRectTemplate">
            <DockPanel 
                Margin="-2,-1,-2,-1">
                <Rectangle
                    Width="14"
                    Height="14"
                    Stroke="Gray"
                    ToolTip="{Binding}"
                    MouseEnter="Rectangle_MouseEnter">
                </Rectangle>
            </DockPanel>
        </DataTemplate>

        <x:Array 
            Type="sys:String" 
            x:Key="tablePickerRowColumn">
            ...items..
            ...items..
            ...items..
        </x:Array>
</r:RibbonWindow.Resources>

<r:RibbonGallery
    Name="_rgInsertTable"
    ScrollViewer.VerticalScrollBarVisibility="Hidden"
    Command="{StaticResource InserirTabelaHandler}"
    MouseLeave="_rgInsertTable_MouseLeave">
    <r:RibbonGalleryCategory
        Name="_rgcInsertTable"
        Header="Inserir tabela..."
        MinColumnCount="10"
        MaxColumnCount="10"
        ItemTemplate="{StaticResource tableRectTemplate}"
        ItemsSource="{Binding Source={StaticResource tablePickerRowColumn}, Path=SyncRoot}">
    </r:RibbonGalleryCategory>
    <r:RibbonSeparator/>
    <r:RibbonMenuItem
        Header="Inserir tabela"
        ImageSource="/Images/Small_32bit/table.png"
        Command="{StaticResource InserirTabelaHandler}"
        MouseEnter="RibbonMenuItem_MouseEnter"/>
</r:RibbonGallery>

你应该使用自定义控件,

演示:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <local:MyTableControl x:Name="MyTableControl"></local:MyTableControl>
    </Grid>
</Window>

对照(XAML):

<UserControl x:Class="WpfApplication1.MyTableControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApplication1"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UniformGrid x:Name="root">

    </UniformGrid>
</UserControl>

控件(代码):

using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

namespace WpfApplication1
{
    public partial class MyTableControl
    {
        private const int MinColumns = 1;
        private const int MaxColumns = 10;
        private const int MinRows = 1;
        private const int MaxRows = 10;

        public static readonly DependencyProperty RowsProperty = DependencyProperty.Register(
            "Rows", typeof (int), typeof (MyTableControl), new PropertyMetadata(MinRows, OnRowsChanged, OnRowsCoerce));

        public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register(
            "Columns", typeof (int), typeof (MyTableControl),
            new PropertyMetadata(MinColumns, OnColumnsChanged, OnColumnsCoerce));

        private bool _pressed;

        public MyTableControl()
        {
            InitializeComponent();
            Columns = 5;
            Rows = 5;
        }

        public int Rows
        {
            get { return (int) GetValue(RowsProperty); }
            set { SetValue(RowsProperty, value); }
        }

        public int Columns
        {
            get { return (int) GetValue(ColumnsProperty); }
            set { SetValue(ColumnsProperty, value); }
        }

        private static object OnRowsCoerce(DependencyObject d, object basevalue)
        {
            var i = (int) basevalue;
            return i < MinRows ? MinRows : i > MaxRows ? MaxRows : i;
        }

        private static object OnColumnsCoerce(DependencyObject d, object basevalue)
        {
            var i = (int) basevalue;
            return i < MinColumns ? MinColumns : i > MaxColumns ? MaxColumns : i;
        }

        private static void OnRowsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control1 = (MyTableControl) d;
            control1.Populate();
        }

        private static void OnColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control1 = (MyTableControl) d;
            control1.Populate();
        }

        private void Populate()
        {
            root.Children.Clear();
            root.Columns = Columns;
            root.Rows = Rows;
            for (var y = 0; y < Rows; y++)
            {
                for (var x = 0; x < Columns; x++)
                {
                    var toggleButton = new ToggleButton {Tag = new Point(x, y)};
                    toggleButton.MouseEnter += ToggleButton_MouseEnter;
                    toggleButton.Click += ToggleButton_Click;
                    root.Children.Add(toggleButton);
                }
            }
        }

        private void ToggleButton_Click(object sender, RoutedEventArgs e)
        {
            _pressed = true; // stops selection
            // little bug here, button will be unchecked since it is a toggle button
            // but since you'll use images instead, this behavior will vanish
        }

        private void ToggleButton_MouseEnter(object sender, MouseEventArgs e)
        {
            if (_pressed)
            {
                return;
            }

            var button = (ToggleButton) sender;
            var point = (Point) button.Tag;
            var x = (int) point.X;
            var y = (int) point.Y;

            for (var i = 0; i < Columns*Rows; i++)
            {
                var element = (ToggleButton) root.Children[i];
                var tag = (Point) element.Tag;
                var x1 = (int) tag.X;
                var y1 = (int) tag.Y;
                element.IsChecked = x1 <= x && y1 <= y;
            }
        }
    }
}

为了简单起见,我使用了 ToggleButton,您可以使用 VisualTreeHelper 而不是 MouseEnter 等进一步改进...

这可能不是最优雅的解决方案,但我是这样解决问题的。

XAML:

<r:RibbonMenuButton
    LargeImageSource="/Images/Large_32bit/table.png"
    Label="Tabela"
    ToolTip="Tabela"
    ToolTipDescription="Insere uma tabela no documento">
    <r:RibbonGallery 
        ScrollViewer.VerticalScrollBarVisibility="Auto">
        <r:RibbonGalleryCategory
            Name="_rgcInsertTable"
            Header="Inserir tabela">
            <Canvas 
                Name="InsertTblCellMnuItemContainer"
                Background="AliceBlue"
                MouseMove="InsertTblCellMnuItemContainer_MouseMove"
                MouseLeave="InsertTblCellMnuItemContainer_MouseLeave"/>
        </r:RibbonGalleryCategory>
        <r:RibbonSeparator/>
        <r:RibbonMenuItem
            Header="Inserir tabela"
            ImageSource="/Images/Small_32bit/table.png"
            Command="{StaticResource InserirTabelaHandler}"/>
    </r:RibbonGallery>
</r:RibbonMenuButton>

代码:

    public MainWindow()
    {
        InitializeComponent();
        PopulateTableInsertMenuItem(10, 8, 15, 15, 2);
    }
    private void ResetTableCellRectangles()
    {
        foreach (Rectangle r in InsertTblCellMnuItemContainer.Children)
        {
            r.Fill = Brushes.AliceBlue;
            r.Stroke = Brushes.Black;
        }
    }

    private void InsertTblCellMnuItemContainer_MouseMove(object sender, MouseEventArgs e)
    {
        Point pos = e.GetPosition(InsertTblCellMnuItemContainer);

        foreach (Rectangle r in InsertTblCellMnuItemContainer.Children)
        {
            Vector posRect = VisualTreeHelper.GetOffset(r);

            if ((posRect.X <= pos.X) && (posRect.Y <= pos.Y))
            {
                r.Fill = Brushes.LightYellow;
                r.Stroke = Brushes.Orange;
            }
            else
            {
                r.Fill = Brushes.AliceBlue;
                r.Stroke = Brushes.Black;
            }
        }
    }

    private void InsertTblCellMnuItemContainer_MouseLeave(object sender, MouseEventArgs e)
    {
        ResetTableCellRectangles();
        _rgcInsertTable.Header = "Inserir tabela";
    }

    private void PopulateTableInsertMenuItem(int width, int height, int rectWidth, int rectHeight, int margin)
    {
        Rectangle r;

        InsertTblCellMnuItemContainer.Width = (rectWidth + margin) * width;
        InsertTblCellMnuItemContainer.Height = (rectHeight + margin) * height;

        for (int j = 0; j < height; ++j)
        {
            for (int i = 0; i < width; ++i)
            {
                // Create new rectangle
                r = new Rectangle
                {
                    Width = rectWidth,
                    Height = rectHeight,
                    Stroke = Brushes.Black,
                    Fill = Brushes.AliceBlue,
                    Tag = new Point(i + 1, j + 1),  // Remember rectangle's position in grid somehow
                };
                r.MouseLeftButtonDown += new MouseButtonEventHandler(TableInsertRectangle_MouseLeftButtonDown);
                r.MouseEnter += new MouseEventHandler(TableInsertRectangle_MouseEnter);

                // Set position in canvas
                Canvas.SetLeft(r, (i * margin) + (i * rectWidth));
                Canvas.SetTop(r, (j * margin) + (j * rectHeight));

                // Add rectangle to canvas
                InsertTblCellMnuItemContainer.Children.Add(r);
            }
        }
    }

    void TableInsertRectangle_MouseEnter(object sender, MouseEventArgs e)
    {
        Point rectKoords = (Point)((Rectangle)sender).Tag;
        _rgcInsertTable.Header = rectKoords.X.ToString() + "x" + rectKoords.Y.ToString() + " tabela";
    }

    void TableInsertRectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        Point rectKoords = (Point)((Rectangle)sender).Tag;
        _textControl.Tables.Add((int)rectKoords.Y, (int)rectKoords.X);
    }

欢迎任何改进。