【问题标题】:UniformGrid with DataTemplate trigger not working as expected, WPF带有 DataTemplate 触发器的 UniformGrid 未按预期工作,WPF
【发布时间】:2017-06-13 14:19:04
【问题描述】:

我在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 显示执行时。为什么不调整用户控件的大小? 图 3 显示了任何调整大小事件。控件正在正确调整大小。

【问题讨论】:

  • 如果StackPanel 更适合您,为什么还需要UniformGrid
  • XAML 中Viewbox 的用途是什么?
  • 我想缩放ItemsControl 以适应Grid。而且,现在我想缩放UserControls 以适应多列中的UniformGrid
  • 我真的不明白你为什么需要Viewbox 来适应UserControlUniformGrid 单元格。默认情况下,放置在GridUniformGrid 内的所有元素的垂直/水平对齐设置为Stretch。我什至浪费了一些时间来编写示例应用程序,我在ItemsControl 中的所有元素都成功缩放以占用网格单元格的所有空间。请显示 UCView 的 XAML。
  • 也可以尝试将ViewboxStretch属性设置为UniformFill等。

标签: wpf itemscontrol stackpanel uniformgrid


【解决方案1】:

好吧,在 cmets 讨论后,我终于解决了您的问题。这一切都与您的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'es 将仅“按边框”调整大小(此行为显示在您的最后一张图片上),字体大小不会更改。如果你想用它们的内容统一缩放你的元素,你真的需要将ItemsControl 包装成Viewbox

【讨论】:

  • 就是@Maxim!我已投票并接受您的答案作为解决方案。谢谢。
【解决方案2】:

这不是一个奇怪的行为,但这是UniformGrid 的工作方式。 作为ItemsControlItemsPanelUniformGrid 使用ItemSource 集合来确定行数和列数。将放置在UniformGrid 中的项目是否可见并不重要——所有网格单元格都具有相同的宽度和高度。所以你的DataTriggerUniformGrid 的布局没有影响,它只会影响项目的可见性。

StackPanel 以不同的方式工作。没有单元格,StackPanel 以占据可用空间的方式排列所有可见项。

【讨论】:

  • 嗯,这很奇怪,因为在设计时 - 项目占用了可用空间。当我编译和执行时,它们不会。我不能使用StackPanel,因为有 64 个用户控件,我希望它们排列成多行,UniformGrid 可以做到。
猜你喜欢
  • 2013-07-19
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
  • 2010-09-10
  • 1970-01-01
相关资源
最近更新 更多