带有 DataTemplate 触发器的 UniformGrid 无法按预期工作,WPF
UniformGrid with DataTemplate trigger not working as expected, WPF
我在一个ItemsControl
中托管了一个包含64个UserControl
的列表,DataContext
是一个对象数组。然后 UserControl
的单个实例的 DataContext
成为对象的实例。
对象有一个名为 Exists
的布尔变量,这是一个 DataTemplate 触发器,用于确定是否显示 Usercontrol
。
我使用 Uniformgrid
来显示列表,但我遇到了一些奇怪的行为。 Usercontrol
不调整大小。见附图。如果我改用 StackPanel
,它就可以正常工作。但我想改用 UnifromGrid
。
这是代码 - 只有 4 个对象将 Exist
变量设置为 true。
<Grid Grid.Row="1" Grid.Column="1" x:Name="gridSome" Background="#FF5AC1F1">
<Viewbox>
<ItemsControl ItemsSource="{Binding SomeVM.SomeModel.SomeArray}"
Margin="15" HorizontalAlignment="Center" VerticalContentAlignment="Center">
<ItemsControl.ItemTemplate>
<DataTemplate>
<tensioner:UCView Margin="5"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Exists}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!--<StackPanel IsItemsHost="true"/> This works-->
<UniformGrid Columns="1"/> <!-- This does not work-->
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Viewbox>
</Grid>
-----更新-----
//SSCCE
主窗口
<Window x:Class="WpfAppItemIssue.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:WpfAppItemIssue"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<!--<Viewbox>-->
<ItemsControl ItemsSource="{Binding Model.Cars}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="ABC"></TextBox>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding exists}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<!--</Viewbox>-->
</Grid>
</Window>
主视图模型
using System.ComponentModel;
namespace WpfAppItemIssue
{
class MainViewModel:INotifyPropertyChanged
{
public MainViewModel()
{
Model = new MainModel();
}
private MainModel model;
public MainModel Model
{
get
{
return model;
}
set
{
model = value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
型号
namespace WpfAppItemIssue
{
class MainModel
{
public Car[] Cars { get; set; }
public MainModel()
{
Cars = new Car[64];
for (int i = 0; i < Cars.Length; i++)
{
Cars[i] = new Car(i);
}
}
}
internal class Car
{
public int someVal { get; set; }
public bool exists { get; set; }
public Car(int someVal)
{
this.someVal = someVal;
if (someVal < 5) //Just enable few items for debug
{
exists = true;
}
else
{
exists = false;
}
}
}
}
见附图:
图1为设计视图。为什么不调整用户控件的大小?
图 2 显示了 On Execute。为什么不调整用户控件的大小?
图 3 显示了 On Any resize 事件。控件正在正确调整大小。
这不是什么奇怪的行为,而是 UniformGrid
的工作方式。
作为 ItemsControl
的 ItemsPanel
,UniformGrid
使用 ItemSource
集合来确定行数和列数。将放置在 UniformGrid
中的项目是否可见并不重要 - 所有网格单元格都具有相同的宽度和高度。所以你的 DataTrigger
对 UniformGrid
的布局没有影响,它只影响项目的可见性。
StackPanel
的工作方式不同。没有单元格,StackPanel
排列所有 visible 项目,使它们占据可用的 space.
好吧,在评论中讨论后,我终于解决了你的问题。在你的 ItemTemplate
中都是关于 DataTrigger
的。只需将其移动到 ItemContainerStyle
Triggers
元素将正确调整大小。
<ItemsControl ItemsSource="{Binding Model.Cars}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Style.Triggers>
<DataTrigger Binding="{Binding exists}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="ABC"></TextBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
请注意,TextBox
只会调整 "by border" 的大小(此行为显示在您的最后一张图片上),字体大小不会更改。如果你想用它们的内容统一缩放你的元素,你真的需要将 ItemsControl
包装到 Viewbox
.
我在一个ItemsControl
中托管了一个包含64个UserControl
的列表,DataContext
是一个对象数组。然后 UserControl
的单个实例的 DataContext
成为对象的实例。
对象有一个名为 Exists
的布尔变量,这是一个 DataTemplate 触发器,用于确定是否显示 Usercontrol
。
我使用 Uniformgrid
来显示列表,但我遇到了一些奇怪的行为。 Usercontrol
不调整大小。见附图。如果我改用 StackPanel
,它就可以正常工作。但我想改用 UnifromGrid
。
这是代码 - 只有 4 个对象将 Exist
变量设置为 true。
<Grid Grid.Row="1" Grid.Column="1" x:Name="gridSome" Background="#FF5AC1F1">
<Viewbox>
<ItemsControl ItemsSource="{Binding SomeVM.SomeModel.SomeArray}"
Margin="15" HorizontalAlignment="Center" VerticalContentAlignment="Center">
<ItemsControl.ItemTemplate>
<DataTemplate>
<tensioner:UCView Margin="5"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Exists}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!--<StackPanel IsItemsHost="true"/> This works-->
<UniformGrid Columns="1"/> <!-- This does not work-->
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Viewbox>
</Grid>
-----更新-----
//SSCCE 主窗口
<Window x:Class="WpfAppItemIssue.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:WpfAppItemIssue"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<!--<Viewbox>-->
<ItemsControl ItemsSource="{Binding Model.Cars}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="ABC"></TextBox>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding exists}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<!--</Viewbox>-->
</Grid>
</Window>
主视图模型
using System.ComponentModel;
namespace WpfAppItemIssue
{
class MainViewModel:INotifyPropertyChanged
{
public MainViewModel()
{
Model = new MainModel();
}
private MainModel model;
public MainModel Model
{
get
{
return model;
}
set
{
model = value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
型号
namespace WpfAppItemIssue
{
class MainModel
{
public Car[] Cars { get; set; }
public MainModel()
{
Cars = new Car[64];
for (int i = 0; i < Cars.Length; i++)
{
Cars[i] = new Car(i);
}
}
}
internal class Car
{
public int someVal { get; set; }
public bool exists { get; set; }
public Car(int someVal)
{
this.someVal = someVal;
if (someVal < 5) //Just enable few items for debug
{
exists = true;
}
else
{
exists = false;
}
}
}
}
见附图:
图1为设计视图。为什么不调整用户控件的大小?
图 2 显示了 On Execute。为什么不调整用户控件的大小?
图 3 显示了 On Any resize 事件。控件正在正确调整大小。
这不是什么奇怪的行为,而是 UniformGrid
的工作方式。
作为 ItemsControl
的 ItemsPanel
,UniformGrid
使用 ItemSource
集合来确定行数和列数。将放置在 UniformGrid
中的项目是否可见并不重要 - 所有网格单元格都具有相同的宽度和高度。所以你的 DataTrigger
对 UniformGrid
的布局没有影响,它只影响项目的可见性。
StackPanel
的工作方式不同。没有单元格,StackPanel
排列所有 visible 项目,使它们占据可用的 space.
好吧,在评论中讨论后,我终于解决了你的问题。在你的 ItemTemplate
中都是关于 DataTrigger
的。只需将其移动到 ItemContainerStyle
Triggers
元素将正确调整大小。
<ItemsControl ItemsSource="{Binding Model.Cars}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Style.Triggers>
<DataTrigger Binding="{Binding exists}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="ABC"></TextBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
请注意,TextBox
只会调整 "by border" 的大小(此行为显示在您的最后一张图片上),字体大小不会更改。如果你想用它们的内容统一缩放你的元素,你真的需要将 ItemsControl
包装到 Viewbox
.