Frage

I have a number of grids that have almost the same layout. This is an example

 <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>

I want to turn this in a controltemplate like here :no template property on grid style in WPF?

But how can I change the Textblock text and Image source when I use a controltemplate ?

War es hilfreich?

Lösung

You can achieve this by creating the one model with Text and Source properties. Then depending on the different number of instance where you want to use this ControlTemplate you can set the model instance in the Tag of your Grid.

<local:MyModel x:Key="myModel1" Text="" Source=""/>


<ContentControl Tag="{StaticResource myModel1}" Template={StaticResource myTemplate}>
</ContentControl>

and in template

<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>

Andere Tipps

As far as I am aware, you can only do this with a DataTemplate and only if each of your data bound classes had properties of the same name, in this case, TextValue and ImageSource. I don't think that you can get access to the data object directly from the 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>

You'd also need to use the ContentTemplate property instead.

<ContentControl Content="{Binding DataObject}" 
    ContentTemplate="{StaticResource Template}" />

This can be done with data-binding, but it would be preferable to use a property interface so that you can simply type something like:

<local:OptionControl Text="Status wijzigen" ImageSource="/UserControlSolution;component/Image/user.png" />

This way you don't need to have your UI labels and icons in a separate data layer.

This can be achieved by creating a control class which defines Dependency Properties, and using TemplateBindings to bind to them in the ControlTemplate.

It's possible that an existing control has appropriate properties that you can create a template for. This HeaderedContentControl template should work for you, although a custom control would be nicer:

<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>

Usage:

<HeaderedContentControl Name="OptionChangeUserState" Grid.Row="0"
                        Style="{StaticResource HeaderedContentControlStyle}"
                        Header="Status wijzigen">
    <BitmapImage>/UserControlSolution;component/Image/user.png</BitmapImage>
</HeaderedContentControl>

Note that we need to wrap the image path in BitmapImage explicitly. This is because the HeaderedContentControl.Content property is not declared as an image type, so WPF will not automatically convert it.

Use DataTemplate with some sort of DTO, DictionaryEntry will do for two items.

    <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>

Usage:

<ContentControl ContentTemplate="{StaticResource gridTemplate}">
<ContentControl.Content>
    <Collections:DictionaryEntry Key="Status wijzigen" Value="/UserControlSolution;component/Image/user.png" />
</ContentControl.Content>

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top