对齐动态实例化的元素

时间:2014-10-15 20:02:06

标签: wpf wpf-controls datatemplate

我在尝试对齐分布在多个数据模板中的内容时遇到了问题。

我正在构建一个灵活的Forms框架,它基本上允许我们在数据库中输入元数据,从这个元数据中水合模型并将这些模型的集合绑定到View。然后,View使用模板选择器根据模型元数据选择要显示到视图的相应UI元素。

例如,以下数据模板是我正在使用的几个:

<DataTemplate DataType="{x:Type models:FormField}"
              x:Key="TextBoxDataTemplate">
    <WrapPanel Margin="5 5 5 0">

        <TextBlock Text="{Binding Path=Description}"
                   Margin="0 0 10 0"
                   HorizontalAlignment="Right"/>
        <formViews:TextInputUserControl />
        </WrapPanel>
</DataTemplate>

<DataTemplate DataType="{x:Type models:FormField}"
              x:Key="MultiLineTextBoxDataTemplate">
    <WrapPanel Margin="5 5 5 0">

        <TextBlock Text="{Binding Path=Description}"
                   HorizontalAlignment="Right"
                   Margin="0 0 10 0" />
        <formViews:MultiLineTextInputUserControl HorizontalAlignment="Left"
                                                 MinWidth="250"
                                                 MinHeight="100"/>
    </WrapPanel>
</DataTemplate>

用户控件只不过是关联视图模型的文本框数据绑定,以及代码隐藏中发生的一些小问题。

当他们渲染到屏幕时,TextBlock宽度会导致关闭。

Description _________
User name ________
Employee Identification ______
etc.

可以将视图切片到各个部分。每个部分都是一个DockPanel,它包含一个ItemsControl,绑定到为每个部分指定的元数据对象集合。

------------------------------------
            Header
------------------------------------

|       |                    |      |
|       |                    |      |
|       |                    |      |
|Left   |     Body           |Right |
|       |                    |      |
|       |                    |      |

------------------------------------
            Footer
------------------------------------

我们尝试了几种解决方案。

解决方案1:使用网格

我们使用WrapPanel代替Grid。 TextBlock放在第0列,用户控件放在第1列。这样可行,但我们必须为第1列中的所有元素提供最小宽度。复选框必须保持与文本框相同的宽度,这看起来并不好。如果我们没有指定最小宽度,则文本框的宽度变为15pt。

我们尝试了各种配置中的Grid列,包括共享大小组。允许不同的元素类型具有不同的宽度会导致布局问题。

另一个问题是,当视图缩小时,我们失去了元素的良好包装。如果某个部分中的ItemsControl未包含任何项目,则停靠面板会折叠。我们想要使用包装面板,以便内容从右向左流动并填充所需的空间。如果右侧部分有物品,则身体会收缩并垂直流动。

这是通过将itemscontrol面板更改为包装面板,并使数据模板中的根容器成为包装面板来实现的。除了对齐问题外,这种方法效果很好。

解决方案2:创建DisplayTextWidth视图模型属性

我们在Windows视图模型中创建了一个DisplayTextWidth属性。由于Forms框架是通用的,我们有几个Windows&amp;以不同的方式使用此框架查看模型。我们将视图模型隐藏在需要DisplayTextWidth的接口后面,然后使用相对路径将每个TextBlock的宽度绑定到它。

public double DisplayTextWidth
{
    get
    {
        return this.displayTextWidth;
    }

    set
    {
        if (value > this.displayTextWidth)
        {
            this.displayTextWidth = value;
            this.OnPropertyChanged();
        }
    }
}

问题是该属性始终为零,并且setter从未被击中。即使绑定设置为双向。

在我的代码中,我将TextBlocks宽度绑定到视图中最宽的textblock元素:

<Label Content="Category:"
        Width="{Binding ActualWidth, ElementName=ContractorLabel}"
        VerticalAlignment="Center"
        HorizontalContentAlignment="Right" />
<ComboBox x:Name="CategoryComboBox"
            MinWidth="200"
            ItemsSource="{Binding EquipmentFilter.EquipmentCategories}"
            SelectedItem="{Binding EquipmentFilter.SelectedEquipmentCategory}"
            Margin="10 0 0 0"
            DisplayMemberPath="Name">

这很有效,给我的结果如下:

Employee _________
     Age _________
   Title _________

虽然没有一点工作,但我无法使用数据模板。我想知道是否应该编写一个依赖属性来遍历可视化树并将TextBlock宽度设置为相同的所有宽度,其中w / e TextBlock的宽度最宽。我可以使用标签装饰数据模板中的TextBlocks,然后查找标签,然后将宽度分配给每个TextBlock以匹配最宽的。

这看起来有点矫枉过正,还有另外一条路可以采取这个措施​​吗?

0 个答案:

没有答案