【问题标题】:Use placeholders in controltemplate在 controltemplate 中使用占位符
【发布时间】:2013-10-16 18:40:08
【问题描述】:
我有许多布局几乎相同的网格。这是一个例子
<Grid x:Name="OptionChangeUserState" Grid.Row="0" Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="Status wijzigen" Margin="0"/>
<Image Grid.Column="1" Source="/UserControlSolution;component/Image/user.png" Margin="5" />
</Grid>
我想把它变成这样的控制模板:no template property on grid style in WPF?
但是当我使用控件模板时,如何更改 Textblock 文本和图像源?
【问题讨论】:
标签:
c#
wpf
controltemplate
【解决方案1】:
您可以通过创建一个具有 Text 和 Source 属性的模型来实现这一点。然后根据您要使用此 ControlTemplate 的不同实例数量,您可以在 Grid 的 Tag 中设置模型实例。
<local:MyModel x:Key="myModel1" Text="" Source=""/>
<ContentControl Tag="{StaticResource myModel1}" Template={StaticResource myTemplate}>
</ContentControl>
在模板中
<ControlTemplate x:Key="myTemplate" TargetType="ContentControl">
<Grid x:Name="OptionChangeUserState" Grid.Row="0" Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="{Binding Tag.Text, RelativeSource={RelativeSource TemplatedParent}}" Margin="0"/>
<Image Grid.Column="1" Source="{Binding Tag.Source, RelativeSource={RelativeSource TemplatedParent}}" Margin="5" />
</Grid>
</ControlTemplate>
【解决方案2】:
据我所知,您只能使用DataTemplate 执行此操作,并且仅如果您的每个数据绑定类都具有相同名称的属性,在本例中为TextValue和ImageSource。我不认为您可以直接从ControlTemplate 访问数据对象。
<DataTemplate>
<Grid x:Name="OptionChangeUserState" Grid.Row="0" Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="{Binding TextValue}" Margin="0"/>
<Image Grid.Column="1" Source="{Binding ImageSource}" Margin="5" />
</Grid>
</DataTemplate>
您还需要改用ContentTemplate 属性。
<ContentControl Content="{Binding DataObject}"
ContentTemplate="{StaticResource Template}" />
【解决方案3】:
这可以通过数据绑定来完成,但最好使用属性接口,这样您就可以简单地键入如下内容:
<local:OptionControl Text="Status wijzigen" ImageSource="/UserControlSolution;component/Image/user.png" />
这样您就不需要将 UI 标签和图标放在单独的数据层中。
这可以通过创建一个定义Dependency Properties的控件类,并在ControlTemplate中使用TemplateBindings绑定到它们来实现。
现有控件可能具有您可以为其创建模板的适当属性。这个HeaderedContentControl 模板应该适合你,虽然自定义控件会更好:
<Style x:Key="HeaderedContentControlStyle" TargetType="HeaderedContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="HeaderedContentControl">
<Grid Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="{TemplateBinding Header}" />
<Image Grid.Column="1" Source="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
用法:
<HeaderedContentControl Name="OptionChangeUserState" Grid.Row="0"
Style="{StaticResource HeaderedContentControlStyle}"
Header="Status wijzigen">
<BitmapImage>/UserControlSolution;component/Image/user.png</BitmapImage>
</HeaderedContentControl>
请注意,我们需要将图像路径明确地包装在BitmapImage 中。这是因为HeaderedContentControl.Content属性没有声明为图片类型,所以WPF不会自动转换。
【解决方案4】:
将 DataTemplate 与某种 DTO 一起使用,DictionaryEntry 将用于两个项目。
<DataTemplate DataType="{x:Type Collections:DictionaryEntry}" x:Key="gridTemplate">
<Grid Style="{StaticResource MenuItemGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource MenuItemTextblockStyle}" Text="{Binding Key}" Margin="0"/>
<Image Grid.Column="1" Source="{Binding Value}" Margin="5" />
</Grid>
</DataTemplate>
用法:
<ContentControl ContentTemplate="{StaticResource gridTemplate}">
<ContentControl.Content>
<Collections:DictionaryEntry Key="Status wijzigen" Value="/UserControlSolution;component/Image/user.png" />
</ContentControl.Content>