Reputation: 12833
Below is a piece of a DataTemplate that defines a strip if commands (buttons with images) for contacting clients. Currently defined for telephone contacts, there are several more commands, so I want to reuse this for other types of contact methods (email, etc.)
The way it and the view models behind it are designed, there are only two things that need to vary to do this:
It seems the most reusable approach would be to have the entire button be itself a DataTemplate with a DataType defined like at the bottom of this post, but I am not grokking how the original DataTemplate would consume this. I've also never used a DataTemplateSelector although that sounds promising.
What is the best approach? How would the code look?
Cheers,
Berryl
<DataTemplate x:Key="TelecomNumbersControlCommands">
<DataTemplate.Resources>
<!-- Image Style -->
<Style TargetType="{x:Type Image}">
<Setter Property="Height" Value="16" />
<Setter Property="Width" Value="16" />
</Style>
</DataTemplate.Resources>
<StackPanel Orientation="Horizontal" Margin="5,0,5,0">
<Button Command="{Binding AddCommand}" >
<Image Source="{resx:Resx Key=Img_Simplicio_Add, ResxName=Presentation.Resources.MasterDetail}" />
<Button.ToolTip>
<TextBlock>
<TextBlock.Text>
<resx:Resx Key="Subject_AddNew_ToolTip" BindingPath="SubjectVm.DisplayName" ResxName="Presentation.Resources.MasterDetail"/>
</TextBlock.Text>
</TextBlock>
</Button.ToolTip>
</Button>
<Button Command="{Binding ContactCommand}" >
<Image Source="{resx:Resx Key=Img_Telephone, ResxName=Smack.Parties.Presentation.Resources.PartyDetailView}" />
<Button.ToolTip>
<TextBlock>
<TextBlock.Text>
<resx:Resx Key="ContactCommand_Telephone_Tooltip" BindingPath="SelectedVm" ResxName="Smack.Parties.Presentation.Resources.PartyDetailView"/>
</TextBlock.Text>
</TextBlock>
</Button.ToolTip>
</Button>
</Button>
<Button Command="{Binding SetDefaultAreaCodeCommand}" >
<Image Source="{resx:Resx Img_Widget, ResxName=Presentation.Resources.MasterDetail}" />
<Button.ToolTip>
<TextBlock>
<TextBlock.Text>
<resx:Resx Key="Subject_Settings" BindingPath="SubjectVm.DisplayName" ResxName="Presentation.Resources.MasterDetail"/>
</TextBlock.Text>
</TextBlock>
</Button.ToolTip>
</Button>
...
</StackPanel>
</DataTemplate>
<Button Command="{Binding ContactCommand}" >
<Button.Resources>
<DataTemplate DataType="{x:Type CmTypes:TelecomNumberPcmShellVm}">
<Image Source="{resx:Resx Key=Img_Telephone, ResxName=Presentation.Resources.PartyDetailView}" >
<Image.ToolTip>
<TextBlock>
<TextBlock.Text>
<resx:Resx
Key="ContactCommand_Telephone_Tooltip"
BindingPath="SelectedVm" ResxName="Presentation.Resources.PartyDetailView"/>
</TextBlock.Text>
</TextBlock>
</Image.ToolTip>
</Image>
</DataTemplate>
</Button.Resources>
<DataTemplate DataType="{x:Type CmTypes:EmailPcmShellVm}">
<Image Source="{resx:Resx Key=Img_Email, ResxName=Presentation.Resources.PartyDetailView}" >
<Image.ToolTip>
<TextBlock>
<TextBlock.Text>
<resx:Resx
Key="ContactCommand_Email_Tooltip"
BindingPath="SelectedVm" ResxName="Presentation.Resources.PartyDetailView"/>
</TextBlock.Text>
</TextBlock>
</Image.ToolTip>
</Image>
</DataTemplate>
</Button>
Object Model
public class PcmShellVm<TCm> : SatelliteViewModel<Party, HashSet<PartyContactMechanism>>
where TCm : ContactMechanism
{
// commands...
}
public class TelephoneNumberPcmShellVm : PcmShellVm<Telephone>
{
...
}
public class EmailPcmShellVm : PcmShellVm<Email>
{
...
}
public class PcmShellVm<TCm> : SatelliteViewModel<Party, HashSet<PartyContactMechanism>>
where TCm : ContactMechanism
{
// commands...
}
public class TelephoneNumberPcmShellVm : PcmShellVm<Telephone>
{
...
}
public class EmailPcmShellVm : PcmShellVm<Email>
{
...
}
Upvotes: 0
Views: 375
Reputation: 132558
Your DataTemplate
in your last code block doesn't work because you are putting the DataTemplate
into Button.Content
. If you put it in <Button.Resources>
, it should work providing Button.Content
is of type CmTypes:TelecomNumberPcmShellVm
In addition, you need to switch to an Image.ToolTip
to add a tooltip to the Image, as Button.ToolTip
is not a valid property for your DataTemplate
<Button Command="{Binding ContactCommand}">
<Button.Resources>
<DataTemplate DataType="{x:Type CmTypes:TelecomNumberPcmShellVm}">
<Image Source="{resx:Resx Key=Img_Telephone, ResxName=Presentation.Resources.PartyDetailView}">
<Image.ToolTip>
<TextBlock>
<TextBlock.Text>
<resx:Resx Key="ContactCommand_Telephone_Tooltip"
BindingPath="SelectedVm"
ResxName="Presentation.Resources.PartyDetailView"/>
</TextBlock.Text>
</TextBlock>
</Image.ToolTip>
</Image>
</DataTemplate>
</Button.Resources>
</Button>
If you actually do want to set Button.ToolTip
instead of Image.ToolTip
, then you will probably need to set it in a DataTrigger
in Button.Style
. Usually for this kind of scenario I have a converter that returns typeof(value)
, so my DataTrigger
looks something like this:
<DataTrigger Binding="{Binding Converter={StaticResource ObjectToTypeConverter}}"
Value="{x:Type CmTypes:TelecomNumberPcmShellVm}">
<Setter Property="ToolTip" ... />
</DataTrigger>
This could also be used to set the Button.ContentTemplate
instead of using implicit data templates as shown above.
Upvotes: 2