【问题标题】:vary a xaml template by type按类型改变 xaml 模板
【发布时间】:2012-11-12 13:06:15
【问题描述】:

下面是一段 DataTemplate,它定义了一条用于联系客户的命令(带图像的按钮)。目前是为电话联系人定义的,还有几个命令,所以我想将它重用于其他类型的联系方式(电子邮件等)

它和它背后的视图模型的设计方式,只有两件事需要改变才能做到这一点:

  1. ContactCommand 按钮的图像和工具提示
  2. 整个最后一个按钮

似乎最可重用的方法是让整个按钮本身成为一个 DataTemplate,并在本文底部定义一个 DataType,但我不知道原始 DataTemplate 将如何使用它。尽管听起来很有希望,但我也从未使用过 DataTemplateSelector。

最好的方法是什么?代码看起来如何?

干杯,
浆果

当前数据模板

<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>
{
    ...
}

【问题讨论】:

  • 您在最后一个代码块中的DataTemplate 不起作用,因为您将DataTemplate 放入Button.Content。如果你把它放在&lt;Button.Resources&gt; 中,它可能会在Button.ContentCmTypes:TelecomNumberPcmShellVm 类型的情况下工作。
  • @Rachel。嗨,Rachel - 我试过了,错误转移到“Button.ToolTip”[在“Button”类型中找不到可附加属性“ToolTip”]。这对你有意义吗?
  • @Rachel。为什么不将您的评论变成答案?我敢肯定你很接近一个。干杯
  • 当然,我将其发布为答案,以及关于ToolTip 的答案。我最初没有将其发布为答案,因为我不确定它是否回答了您的问题:)

标签: wpf xaml mvvm datatemplate


【解决方案1】:

您在最后一个代码块中的DataTemplate 不起作用,因为您将DataTemplate 放入Button.Content。如果你把它放在&lt;Button.Resources&gt; 中,它应该可以工作,前提是Button.Content 的类型是CmTypes:TelecomNumberPcmShellVm

此外,您需要切换到Image.ToolTip 以向图像添加工具提示,因为Button.ToolTip 不是您的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>

如果您确实想设置Button.ToolTip 而不是Image.ToolTip,那么您可能需要在Button.Style 中的DataTrigger 中设置它。通常对于这种情况,我有一个返回 typeof(value) 的转换器,所以我的 DataTrigger 看起来像这样:

<DataTrigger Binding="{Binding Converter={StaticResource ObjectToTypeConverter}}" 
             Value="{x:Type CmTypes:TelecomNumberPcmShellVm}">
    <Setter Property="ToolTip" ... />
</DataTrigger>

这也可用于设置Button.ContentTemplate,而不是使用如上所示的隐式数据模板。

【讨论】:

  • 所以它编译但不起作用;意味着它根本不会出现。由于没有数据绑定错误(并且绑定命令有效),我猜这表明它由于某种原因找不到类型。请在发布结束时查看修订!
  • 认为我喜欢这种情况下的转换器解决方案,因为我实际上可以重用它并使 xaml 更精简;但我并不肯定我知道如何编码。似乎 DataTemplateSelector 方法也可能有效,但我也不知道如何编写代码!所以我将把这个问题作为一个单独的问题提出一个变体——这样这篇文章就不会变得比现在更复杂,你可以有机会获得更多的积分,这显然是你需要的:- -)
  • @Berryl 修改后的 XAML 中的 Button.Content 仍设置为 DataTemplate。如果Button.Content 设置为TelecomNumberPcmShellVm 类型的对象(例如Content="{Binding SomeTelecomNumberProperty}"),它将使用Button.Resources 中定义的DataTemplate 来绘制该项目。
  • 是的,只需输入 'Content = {Binding}' 就可以了。如果你可以的话,喜欢它look at [this other question。干杯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-08
  • 2015-11-10
  • 1970-01-01
  • 2022-01-12
相关资源
最近更新 更多