我有一个UserControl可以在网格上排列模板化项目(基于this问题的答案)。现在我想让该网格的列/行可以调整大小。
现在,我有一些黑客攻击我检测鼠标事件并计算用户是否在边界附近点击。如果是这样,它会调整相应的列。这主要是有效的,但我遇到了相对较慢的MouseMove事件触发问题,使用户难以点击正确的位置。此外,我无法扩展最后一行/列的大小,因为鼠标现在移动到我无法跟踪它的控制区域之外(尽管我可以通过更多的工作来解决这个问题)。
更好的解决方案是将GridSplitters添加到每个列/行。问题是,我的UserControl使用ItemsControl和DataTemplate来创建项目,所以我很难搞清楚如何添加拆分器。我可以修改用户定义的模板吗?还有其他方法可以添加分割器吗?
*编辑*
这是我想要做的一个例子(如果网格单元是手动定义的,而不是通过ItemsControl定义的)。请注意,此示例仍无法解决调整大小的最后一行问题。
<Grid
Grid.Row="2" Grid.Column="1"
>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Text="Row 0" Grid.Row="0"/>
<GridSplitter
Grid.Row="0"
Height="5"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Background="Transparent"/>
<TextBox Text="Row 1" Grid.Row="1"/>
<GridSplitter
Grid.Row="1"
Height="5"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Background="Transparent"/>
<TextBox Text="Row 2" Grid.Row="2"/>
<GridSplitter
Grid.Row="2"
Height="5"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Background="Transparent"/>
</Grid>
答案 0 :(得分:0)
可以通过将列的宽度绑定到viewmodel上的属性来完成列。这样,当GridSplitter移动时,它将更新属性,进而更新其他项。
对于Rows,只需将GridSplitter添加到DataTemplate的底部就可以满足您的需求。
我创建了一个小hacky示例应用程序来说明:
我的窗口:
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
DataContext = new Context();
ItemsControl.ItemsSource = new ObservableCollection<Foo>
{
new Foo("Hello", "World1"),
new Foo("Hello1", "World2"),
new Foo("Hello2", "World3")
};
}
}
在Xaml中:
<ItemsControl Name="ItemsControl" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type utility:Foo}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Path=DataContext.Width, RelativeSource={RelativeSource FindAncestor, AncestorType=utility:MainWindow}, Mode=TwoWay}" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="5" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Path=Name}" Grid.Column="0" Grid.Row="0" Margin="5"/>
<GridSplitter Grid.Column="1" Grid.Row="0" Width="5" Height="Auto" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext" ResizeDirection="Columns" />
<TextBlock Text="{Binding Path=Title}" Grid.Column="2" Grid.Row="0" Margin="5"/>
<GridSplitter Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="1" Height="5" Width="Auto" HorizontalAlignment="Stretch" ResizeBehavior="PreviousAndCurrent" ResizeDirection="Rows" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
使用以下数据上下文和项目:
public class Foo
{
public Foo(string name, string title)
{
Name = name;
Title = title;
}
public string Name { get; set; }
public string Title { get; set; }
}
public class Context : INotifyPropertyChanged
{
private GridLength _width = new GridLength(60);
public GridLength Width
{
get { return _width; }
set
{
if (_width == value) return;
_width = value;
RaisePropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
需要注意的一点是 - 我的viewmodel的Width属性无法初始化为GridLength.Auto - 否则所有列都不会排列。