我有一大块xaml,它复制相同的模式六次,并希望通过消除重复来减少这种占用空间。我遇到了一个需要帮助的障碍。
背景:我有一个类,它实例化另一个类六次(项目的各个阶段)。
public ECN(string ecnNumber) {
_ECNNumber = ecnNumber;
//instantiate each phase to be populated or not
_PurchaseParts = new ECNPhase();
_PieceParts = new ECNPhase();
_Weldments = new ECNPhase();
_BOMCfg = new ECNPhase();
_Cleanup = new ECNPhase();
_PRAF = new ECNPhase();
}
每个阶段内部都是ECNPhase类中引用的Changes(另一个类)的集合。每个阶段都有一个独特的数据,每个阶段都以独特的视图显示,这是我稍后会展示的障碍。
重复xaml代码的示例,主要区别在于每个扩展器内的不同视图:
<StackPanel Margin="0">
<!--Section for Purchase parts-->
<StackPanel Orientation="Horizontal" >
<CheckBox Margin="0,5,5,5" IsChecked="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts.HasPhase,Mode=TwoWay}"/>
<StackPanel Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts.HasPhase}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Expander Header="Purchase Parts" Margin="0,0,10,0" Width="110">
<view:PurchasePartsView/>
</Expander>
<CheckBox Content="Submit" Margin="10,5,0,5"/> <!--add a command to handle the submit checkbox event-->
<Label Content="Status:" Margin="10,0,0,0" HorizontalContentAlignment="Right" Width="60"/>
<Label Content="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts.Status}"/>
</StackPanel>
</StackPanel>
<!--Section for Piece Parts-->
<StackPanel Orientation="Horizontal">
<CheckBox Margin="0,5,5,5" IsChecked="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts.HasPhase,Mode=TwoWay}"/>
<StackPanel Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts.HasPhase}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Expander Header="Piece Parts" Margin="0,0,10,0" Width="110">
<view:PiecePartsView/>
</Expander>
<CheckBox Content="Submit" Margin="10,5,0,5"/> <!--add a command to handle the submit checkbox event-->
<Label Content="Status:" Margin="10,0,0,0" HorizontalContentAlignment="Right" Width="60"/>
<Label Content="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts.Status}"/>
</StackPanel>
</StackPanel>
<!--duplicated four more times-->
</StackPanel>
我想做的是:
<StackPanel>
<view:PhaseView DataContext="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts}"/>
<view:PhaseView DataContext="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts}"/>
<!--four more phases-->
</StackPanel>
PhaseView将成为处理复制的模板,这就是我遇到麻烦的地方。每个阶段都需要一个基于PhaseView的datacontext选择的唯一视图(userControl)。
<StackPanel Orientation="Horizontal" >
<CheckBox Margin="0,5,5,5" IsChecked="{Binding Path=HasPhase,Mode=TwoWay}"/>
<StackPanel Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=HasPhase}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Expander Header="DisplayName" Margin="0,0,10,0" Width="110">
<!--add somthing here to select the correct view based on the datacontext-->
<!--<local:PurchasePartsView/> This user control adds a datagrid that is unique to each phase-->
</Expander>
<CheckBox Content="Submit" Margin="10,5,0,5"/> <!--add a command to handle the submit checkbox event-->
<Label Content="Status:" Margin="10,0,0,0" HorizontalContentAlignment="Right" Width="60"/>
<Label Content="{Binding Path=Status}"/>
</StackPanel>
</StackPanel>
我正在考虑使用数据触发器以某种方式显示如下,但我没有任何运气搞清楚。我知道必须有办法做到这一点,这可能是简单而愚蠢的事情。任何帮助将不胜感激。
<DataTrigger Binding="{Binding Path=DisplayName}" Value="Purchase Parts">
<Setter Property="DataContext" Value="{Binding }"/> <!--Don't know how to bind the DataContext-->
</DataTrigger>
谢谢,
答案 0 :(得分:0)
好的,感谢Bradley,我查看了DataTemplateSelector,这就是我想出来的。
在我的UserControl资源中,我设置了几个DataTemplates和一个覆盖DataTemplateSelector类的TemplateSelector类的引用。
XAML资源:
<UserControl.Resources>
<local:TemplateSelector x:Key="myTemplateSelector"/>
<DataTemplate x:Key="PurchasePartsTemplate">
<view:PurchasePartsView/>
</DataTemplate>
<DataTemplate x:Key="PiecePartsTemplate">
<view:PiecePartsView/>
</DataTemplate>
<!--Four more templates-->
</UserControl.Resources>
DataTemplateSelector覆盖的代码隐藏。注意:我无法找到绑定到ECNPhase类的方法,因此我绑定到类中的DisplayName属性以提取正确的实例。
class TemplateSelector : DataTemplateSelector {
public override DataTemplate SelectTemplate(object item, DependencyObject container) {
FrameworkElement element = container as FrameworkElement;
if(element != null && item != null && item is string) {
string phase = (string)item;
if(phase == "Purchase Parts") {
return element.FindResource("PurchasePartsTemplate") as DataTemplate;
}else if(phase == "Piece Parts") {
return element.FindResource("PiecePartsTemplate") as DataTemplate;
}
}
return null;
}
}
我在我的UserContol中调用此类,如下所示:
<Expander Header="{Binding Path=DisplayName}" Margin="0,0,10,0" Content="{Binding Path=DisplayName}"
ContentTemplateSelector="{StaticResource myTemplateSelector}"/>
没有与扩展器关联的项控件,因此我使用了内容控件。我将DisplayName传递给control属性,contentTemplateSelector使用myTemplateSelector资源进入代码隐藏,并根据DisplayName选择要使用的相应datatemplate。
现在我可以这样调用我的可重用模板:
<StackPanel Margin="0">
<view:ChangePhaseView DataContext="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts}"/>
<view:ChangePhaseView DataContext="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts}"/>
</StackPanel>
@Bradley,谢谢你指出我正确的方向。