我在尝试调整跨多个数据模板的内容时遇到问题 .

我正在构建一个灵活的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,该ItemsControl绑定到为每个部分指定的元数据对象集合 .

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

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

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

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

解决方案1:使用网格

而不是 WrapPanel ,我们使用 Grid . TextBlock放在第0列,用户控件放在第1列 . 这样可行,但我们必须为第1列中的所有元素提供最小宽度 . 复选框必须保持与文本框相同的宽度,而文本框没有指定最小宽度,然后文本框的宽度变为15pt .

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

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

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

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

我们在Windows视图模型中创建了一个DisplayTextWidth属性 . 由于Forms框架是通用的,我们有几个以不同方式使用此框架的Windows和视图模型 . 我们将视图模型隐藏在需要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的宽度最宽 . 我可以使用Tag在Data-Template中装饰TextBlocks,然后查找Tag,然后将Width分配给每个TextBlock以匹配最宽的 .

这看起来有点矫枉过正,还有另一条路要走吗?