根据绑定对象的数据类型将模板应用于内容控件
Applying template to a contentcontrol based on data type of bound object
我遇到了以下问题:
我需要制作一个自定义的 ContentControl,当它没有聚焦时会有一个默认的 DataTemplate,里面有一个 TextBlock,但是当聚焦时(即通过鼠标或键盘)应该能够根据类型呈现另一个合适的 DataTemplate内容。例如,假设如果 Content 的类型是 String,那么应该显示一个带有 TextBox 的 DataTemplate,如果是 DateTime - 那么一个 DateTimePicker,等等。
我知道有一种方法可以根据 Focused/NotFocused 为 ListBoxItems 提供不同的 DataTemplates,我已经通过应用带有触发器的样式来实现它。但在这种情况下,我被困住了。
我已经尝试过使用 Style,但没有成功。
这是我到目前为止的想法:
Themes/generix.xaml 对于刚从 ContentControl 继承的 Gadget 控件:
<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)));
}
这是测试类:
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; }
}
这是值转换器:
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 对象编辑为 return 类型而不是字符串。上面截断的代码已相应修复。
绑定到 {RelativeSource Self}
的内容 属性 和 return 来自转换器 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();
}
}
我遇到了以下问题:
我需要制作一个自定义的 ContentControl,当它没有聚焦时会有一个默认的 DataTemplate,里面有一个 TextBlock,但是当聚焦时(即通过鼠标或键盘)应该能够根据类型呈现另一个合适的 DataTemplate内容。例如,假设如果 Content 的类型是 String,那么应该显示一个带有 TextBox 的 DataTemplate,如果是 DateTime - 那么一个 DateTimePicker,等等。
我知道有一种方法可以根据 Focused/NotFocused 为 ListBoxItems 提供不同的 DataTemplates,我已经通过应用带有触发器的样式来实现它。但在这种情况下,我被困住了。 我已经尝试过使用 Style,但没有成功。
这是我到目前为止的想法:
Themes/generix.xaml 对于刚从 ContentControl 继承的 Gadget 控件:
<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)));
}
这是测试类:
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; }
}
这是值转换器:
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 对象编辑为 return 类型而不是字符串。上面截断的代码已相应修复。
绑定到 {RelativeSource Self}
的内容 属性 和 return 来自转换器 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();
}
}