我试图在WPF中创建一个包含两列和两行的网格。我希望网格以一种特殊的方式调整大小,具体取决于哪些单元格可见,我已经做了一些插图来更好地解释:
案例1:一个项目可见 - 一个单元格填充所有可用空间
案例2;有两个项目可见 - 空间在行之间划分
案例3:可见三个项目 - 第2行分为两列
案例4:所有四个项目都可见 - 空间均匀分布
这篇文章:Resizing WPF Grid Column when other Columns children is collapsed?
描述如何使用可见性大小转换器解决单行的问题,但为了使其适用于两行,我必须将一行的大小绑定到两个元素的可见性。使用多重绑定可能是可能的,但我不确定这是否是最好的方法。也许有更好的方法来做这个而不是使用网格?
答案 0 :(得分:1)
有点儿有趣的问题。基本上你想要在类中封装可移动项的概念,这样你就可以轻松地将Grid props绑定到可编程的东西上。在我的想法中,我为此创建了一个类型Cell
。现在,当您希望布局移动时,您可以将所有道具绑定到一个对象。您将在视图模型中看到4种方法:ShowAllCells
,Show3Cells
等,这些都是您根据表示逻辑调用的。认为这就是它。
<强> XAML 强>
<Window x:Class="WpfApplication7.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:WpfApplication7"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
d:DataContext="{d:DesignInstance {x:Type local:MainWindowViewModel}}">
<Window.Resources>
<Style TargetType="Rectangle">
<Setter Property="Width" Value="50"/>
<Setter Property="Height" Value="50"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle Fill="Red" Grid.Row="{Binding Cell1.Row}" Grid.Column="{Binding Cell1.Col}" Grid.ColumnSpan="{Binding Cell1.ColSpan}" Grid.RowSpan="{Binding Cell1.RowSpan}" Visibility="{Binding Cell1.Vis}" />
<Rectangle Fill="Blue" Grid.Row="{Binding Cell2.Row}" Grid.Column="{Binding Cell2.Col}" Grid.ColumnSpan="{Binding Cell2.ColSpan}" Grid.RowSpan="{Binding Cell2.RowSpan}" Visibility="{Binding Cell2.Vis}" />
<Rectangle Fill="Yellow" Grid.Row="{Binding Cell3.Row}" Grid.Column="{Binding Cell3.Col}" Grid.ColumnSpan="{Binding Cell3.ColSpan}" Grid.RowSpan="{Binding Cell3.RowSpan}" Visibility="{Binding Cell3.Vis}" />
<Rectangle Fill="Green" Grid.Row="{Binding Cell4.Row}" Grid.Column="{Binding Cell4.Col}" Grid.ColumnSpan="{Binding Cell4.ColSpan}" Grid.RowSpan="{Binding Cell4.RowSpan}" Visibility="{Binding Cell4.Vis}" />
</Grid>
View-Model&amp;细胞强>
using System.ComponentModel;
using System.Windows;
namespace WpfApplication7
{
public class Cell : INotifyPropertyChanged
{
private int row;
public int Row
{
get { return row; }
set
{
if (row == value) return;
row = value;
OnPropertyChanged(@"Row");
}
}
private int col;
public int Col
{
get { return col; }
set
{
if (col == value) return;
col = value;
OnPropertyChanged(@"Col");
}
}
private int rowSpan;
public int RowSpan
{
get { return rowSpan; }
set
{
if (rowSpan == value) return;
rowSpan = value;
OnPropertyChanged(@"RowSpan");
}
}
private int colSpan;
public int ColSpan
{
get { return colSpan; }
set
{
if (colSpan == value) return;
colSpan = value;
OnPropertyChanged(@"ColSpan");
}
}
private Visibility vis;
public Visibility Vis
{
get { return vis; }
set
{
if (vis == value) return;
vis = value;
OnPropertyChanged(@"Vis");
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler == null) return;
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
#endregion
}
public class MainWindowViewModel
{
public MainWindowViewModel()
{
Cell1 = new Cell();
Cell2 = new Cell();
Cell3 = new Cell();
Cell4 = new Cell();
// Call the one you want.
ShowAllCells();
Show3Cells(Cell2, Cell3, Cell4, Cell1);
Show2Cells(Cell2, Cell3, Cell4, Cell1);
Show1Cell(Cell2, Cell3, Cell4, Cell1);
}
private void ShowAllCells()
{
Cell1.Row = 0;
Cell1.Col = 0;
Cell1.RowSpan = 1;
Cell1.ColSpan = 1;
Cell1.Vis = Visibility.Visible;
Cell2.Row = 0;
Cell2.Col = 1;
Cell2.RowSpan = 1;
Cell2.ColSpan = 1;
Cell2.Vis = Visibility.Visible;
Cell3.Row = 1;
Cell3.Col = 0;
Cell3.RowSpan = 1;
Cell3.ColSpan = 1;
Cell3.Vis = Visibility.Visible;
Cell4.Row = 1;
Cell4.Col = 1;
Cell4.RowSpan = 1;
Cell4.ColSpan = 1;
Cell4.Vis = Visibility.Visible;
}
private void Show3Cells(Cell one, Cell two, Cell three, Cell hidden1)
{
one.Row = 0;
one.Col = 0;
one.RowSpan = 1;
one.ColSpan = 2;
one.Vis = Visibility.Visible;
two.Row = 1;
two.Col = 0;
two.RowSpan = 1;
two.ColSpan = 1;
two.Vis = Visibility.Visible;
three.Row = 1;
three.Col = 1;
three.RowSpan = 1;
three.ColSpan = 1;
three.Vis = Visibility.Visible;
hidden1.Row = 0;
hidden1.Col = 0;
hidden1.RowSpan = 1;
hidden1.ColSpan = 1;
hidden1.Vis = Visibility.Collapsed;
}
private void Show2Cells(Cell one, Cell two, Cell hidden1, Cell hidden2)
{
one.Row = 0;
one.Col = 0;
one.RowSpan = 1;
one.ColSpan = 2;
one.Vis = Visibility.Visible;
two.Row = 1;
two.Col = 0;
two.RowSpan = 1;
two.ColSpan = 2;
two.Vis = Visibility.Visible;
hidden1.Row = 0;
hidden1.Col = 0;
hidden1.RowSpan = 1;
hidden1.ColSpan = 1;
hidden1.Vis = Visibility.Collapsed;
hidden2.Row = 0;
hidden2.Col = 0;
hidden2.RowSpan = 1;
hidden2.ColSpan = 1;
hidden2.Vis = Visibility.Collapsed;
}
private void Show1Cell(Cell one, Cell hidden1, Cell hidden2, Cell hidden3)
{
one.Row = 0;
one.Col = 0;
one.RowSpan = 2;
one.ColSpan = 2;
one.Vis = Visibility.Visible;
hidden1.Row = 0;
hidden1.Col = 0;
hidden1.RowSpan = 1;
hidden1.ColSpan = 1;
hidden1.Vis = Visibility.Collapsed;
hidden2.Row = 0;
hidden2.Col = 0;
hidden2.RowSpan = 1;
hidden2.ColSpan = 1;
hidden2.Vis = Visibility.Collapsed;
hidden3.Row = 0;
hidden3.Col = 0;
hidden3.RowSpan = 1;
hidden3.ColSpan = 1;
hidden3.Vis = Visibility.Collapsed;
}
public Cell Cell1 { get; set; }
public Cell Cell2 { get; set; }
public Cell Cell3 { get; set; }
public Cell Cell4 { get; set; }
}
}