WPF嵌套模板引发的血案
<div id="cnblogs_post_body">有些事情看似简单,在进行的过程中往往遇到大的麻烦;有些问题小之又小,但躲在角落里窃笑的它能让你呕血数日。反正我不止一次遇到过这样的情况。日前我打算在产品中加入吊牌打印的功能,涉及到合格证的制作。大伙都有去商店里买衣服的经历,留意看吊牌的话会看到成分一栏里分成好几个类别,如面料、里料、夹层等,每一类别又有好几个物料占比信息,如面料包含70%的棉和30%的xx纤维。如何能让用户较为方便地设置这些信息呢?我原本打算采用自定义集合控件的方式,但是有些问题不好解决,部分难点问题记录在随笔WPF自定义集合控件概述与遇到的问题中。于是我老老实实采用为ListBox新建Template的方式,期望达到如下效果:
http://images.cnitblog.com/blog/474041/201212/30024631-0a3d6f1e9a134ea996036aa1614ead27.png
毫无疑问,上述效果需要俩ListBox,一个呈现大类,一个呈现小类,还得为它们准备各自的DataTemplate,还需要俩GroupBox,它们各自的HeaderTemplate也要额外处理。我微微一笑,流利地敲出代码的第一版本:
<div class="cnblogs_code"> 1 <GroupBox DataContext="{Binding Composition,Mode=TwoWay,Converter={StaticResource compositionConverter}}" 2 RenderOptions.BitmapScalingMode="NearestNeighbor" Padding="3"> 3 <GroupBox.HeaderTemplate> 4 <DataTemplate> 5 <StackPanel Orientation="Horizontal"> 6 <TextBlock Text="成分" /> 7 <!--猜测由于没有给GroupBox.Header赋予Content,因此HeaderTemplate里的控件的DataContext为Null--> 8 <!--猜测正确,具体请看WPF GroupBox HeaderTemplate and DataBinding http://stackoverflow.com/questions/2425079/wpf-groupbox-headertemplate-and-databinding--> 9 <Button x:Name="PART_AddButton" Height="16" Click="PART_AddButton_Click">10 <Button.Content>11 <Image Source="pack://application:,,,/View.Extension;Component/Images/plus.png" />12 </Button.Content>13 </Button>14 <Button x:Name="PART_DeleteButton" Height="16" Click="PART_DeleteButton_Click">15 <Button.Content>16 <Image Source="pack://application:,,,/View.Extension;Component/Images/minus.png" />17 </Button.Content>18 </Button>19 </StackPanel>20 </DataTemplate>21 </GroupBox.HeaderTemplate>22 <ListBox x:Name="lbxMateriels" ItemsSource="{Binding}" BorderThickness="0" ScrollViewer.VerticalScrollBarVisibility="Hidden">23 <ListBox.ItemContainerStyle>24 <Style TargetType="ListBoxItem">25 <Setter Property="Margin" Value="2" />26 <Setter Property="Template">27 <Setter.Value>28 <ControlTemplate TargetType="ListBoxItem"> 29 <GroupBox Header="{Binding}">30 <GroupBox.HeaderTemplate>31 <DataTemplate>32 <StackPanel Orientation="Horizontal">33 <ComboBox ItemsSource="{Binding MaterielKinds,Source={StaticResource context}}" 34 MinWidth="60"35 SelectedValue="{Binding KindName}"36 SelectedValuePath="Name"37 DisplayMemberPath="Name" />38 <Button Height="16" Click="btnAddPercent_Click">39 <Button.Content>40 <Image Source="pack://application:,,,/View.Extension;Component/Images/plus.png" />41 </Button.Content>42 </Button>43 <Button Height="16" Click="btnDeletePercent_Click">44 <Button.Content>45 <Image Source="pack://application:,,,/View.Extension;Component/Images/minus.png" />46 </Button.Content>47 </Button>48 </StackPanel>49 </DataTemplate>50 </GroupBox.HeaderTemplate>51 <ListBox x:Name="lbxMaterielPercents" ScrollViewer.VerticalScrollBarVisibility="Hidden"52 ItemsSource="{Binding MaterielPercents}" BorderThickness="0">53 <ListBox.ItemTemplate>54 <DataTemplate>55 <Grid Margin="0 3 0 0">56 <Grid.ColumnDefinitions>57 <ColumnDefinition Width="Auto" />58 <ColumnDefinition Width="*" />59 </Grid.ColumnDefinitions>60 <NumericUpDown Value="{Binding Percent}" Minimum="0" Maximum="100" CustomUnit="%" />61 <ComboBox ItemsSource="{Binding AvailableMateriels,Source={StaticResource context}}"62 SelectedValue="{Binding MaterielName}"63 SelectedValuePath="Name"64 DisplayMemberPath="Name"65 Grid.Column="1" MinWidth="60" Margin="5 0 0 0"/>66 </Grid>67 </DataTemplate>68 </ListBox.ItemTemplate>69 </ListBox>70 </GroupBox>71 </ControlTemplate>72 </Setter.Value>73 </Setter>74 </Style>75 </ListBox.ItemContainerStyle>76 </ListBox>77 </GroupBox>
页:
[1]