我在尝试调整跨多个数据模板的内容时遇到问题 .
我正在构建一个灵活的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以匹配最宽的 .
这看起来有点矫枉过正,还有另一条路要走吗?