根据绑定对象的数据类型将模板应用于contentcontrol

时间:2017-01-05 15:10:29

标签: c# wpf xaml datatemplate controltemplate

我遇到了以下问题:

我需要制作一个自定义的ContentControl,当没有聚焦时,会有一个带有TextBlock的默认DataTemplate,但是当聚焦(即鼠标或键盘)应该能够根据内容的类型呈现另一个合适的DataTemplate时。例如,让我们说如果Content的类型是String,那么应该显示带有TextBox的DataTemplate,如果它是DateTime - 然后是DateTimePicker,依此类推。

我知道有一种方法可以提供不同的DataTemplates,具体取决于ListBoxItems的Focused / NotFocused,我已经通过应用带触发器的Style实现了这一点。但在这种情况下,我被困住了。 我已经尝试过Style,但没有成功。

这是我到目前为止所提出的:

主题/ generix.xaml用于Gadget控件,它刚从ContentControl继承而来:

<ControlTemplate x:Key="String">
    <Border BorderBrush="Green" BorderThickness="1">
        <TextBlock Text="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"></TextBlock>
    </Border>
</ControlTemplate>
<ControlTemplate x:Key="Int32">
    <Border BorderBrush="Blue" BorderThickness="1">
        <TextBlock Text="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"></TextBlock>
    </Border>
</ControlTemplate>
<ControlTemplate x:Key="Base">
    <Border BorderBrush="Yellow" BorderThickness="1">
        <TextBlock Text="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"></TextBlock>
    </Border>
</ControlTemplate>
<local:DTC x:Key="DataTypeConverter"></local:DTC>
<Style TargetType="{x:Type local:Gadget}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:Gadget}},  Converter={StaticResource DataTypeConverter}}" Value="String}">
            <Setter Property="Template" Value="{StaticResource String}"></Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding Content,  RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:Gadget}}, Converter={StaticResource DataTypeConverter}}" Value="Int32}">
            <Setter Property="Template" Value="{StaticResource Int32}"></Setter>
        </DataTrigger>
    </Style.Triggers>
    <Setter Property="Padding"
            Value="2" />
    <Setter Property="Template" Value="{StaticResource Base}"> </Setter>
</Style>

Gadget控件后端只有一个静态构造函数:

static Gadget()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(Gadget),
                   new FrameworkPropertyMetadata(typeof(Gadget)));

    }

这是TestClass:

public class TestClass
{
    public TestClass(string one, string two)
    {
        One = one;
        Two = two;
        Three = count++;
    }

    static int count = 0;

    public string One { get; set; } = "One1";
    public string Two { get; set; } = "Two2";
    public int Three { get; set; }
}

这是valueConverter:

public class DTC : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
      CultureInfo culture)
    {
        return value.GetType();
    }

    public object ConvertBack(object value, Type targetType, object parameter,
      CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

这就是我尝试在ListBox中使用它的方法

<ListBox Name="lstBox" Margin="10,10,172,40">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <local:Gadget Content="{Binding Path=One}"></local:Gadget>
                    <local:Gadget Content="{Binding Path=Two}"></local:Gadget>
                    <local:Gadget Content="{Binding Path=Three}"></local:Gadget>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

我到处搜索,但要么我不能很好地提出我的问题,要么也许根本没有人需要......

我真的很感激有关此事的任何建议!

提前多多感谢!

修改

为了使mm8工作的建议我编辑了DTC对象以返回Type而不是String。上面修剪的代码也是相应修复的。

1 个答案:

答案 0 :(得分:0)

绑定到{RelativeSource Self}的Content属性,并从转换器的Convert方法返回实际类型:

<Style TargetType="{x:Type local:Gadget}" xmlns:s="clr-namespace:System;assembly=mscorlib">
    <Setter Property="Padding" Value="2" />
    <Setter Property="Template" Value="{StaticResource Base}"></Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource Self}, Converter={StaticResource DataTypeConverter}}" 
                     Value="{x:Type s:String}">
            <Setter Property="Template" Value="{StaticResource String}"></Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource Self}, Converter={StaticResource DataTypeConverter}}" 
                     Value="{x:Type s:Int32}">
            <Setter Property="Template" Value="{StaticResource Int32}"></Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>
public class DTC : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value.GetType();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}