多项选择
Selection of multiple items
我正在使用 RibbonControlsLibrary、WPF 和 VS2015,我需要对多个 RibbonGallery 的选择执行操作。跟着图方便理解。
遵循已完成的代码:
<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);
}
欢迎任何改进。
我正在使用 RibbonControlsLibrary、WPF 和 VS2015,我需要对多个 RibbonGallery 的选择执行操作。跟着图方便理解。
遵循已完成的代码:
<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);
}
欢迎任何改进。