我为所需的ContentControl.DataTemplateSelector 设置了一个模板选择器。
我希望能够通过XAML或代码根据命令或其他方式调用ContentControl,从选择器中重新选择模板。
谢谢。
我希望能够通过XAML或代码根据命令或其他方式调用ContentControl,从选择器中重新选择模板。
谢谢。
虽然晚到了,但我知道这个问题。
在面对此问题时,我发现最简单的方法是明确地设置一个新的TemplateSelector,例如:
MyContentControl.ContentTemplateSelector =
new MyDataTemplateSelector();
ContentControl
的ContentTemplate
属性上使用ValueConverter
而非DataTemplateSelector
。DataContext
中绑定一个属性(例如ScreenNumber
),然后在ValueConverter
中返回与该ScreenNumber
相关联的DataTemplate
即可。ValueConverter
:public class ValueDataTemplateConverter : IValueConverter
{
public DataTemplate TemplateA { get; set; }
public DataTemplate TemplateB { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is ValueType valueType)
switch (valueType)
{
case ValueType.TypeA:
return TemplateA;
case ValueType.TypeB:
return TemplateB;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
示例 XAML 资源:
<converters:ValueDataTemplateConverter x:Key="ValueDataTemplateConverter">
<converters:ValueDataTemplateConverter.TemplateA>
<DataTemplate>
<TextBox Text="{Binding Value}" />
</DataTemplate>
</converters:ValueDataTemplateConverter.TemplateA>
<converters:ValueDataTemplateConverter.TemplateB>
<DataTemplate>
<CheckBox IsChecked="{Binding Value}" />
</DataTemplate>
</converters:ValueDataTemplateConverter.TemplateB>
</converters:ValueDataTemplateConverter>
我不知道有没有(非笨拙的)方法可以做到这一点:当WPF需要选择模板时,DataTemplateSelector会被调用,而就WPF而言,这是一次性的决策。 (您可以通过让WPF认为内容已更改来欺骗它,例如将内容设置为null,然后再设置回来-我认为这样可以工作,但尚未测试-但这相当丑陋!)如果有一种好的方法来做到这一点,我也很想知道!
但是,还有一种替代方式可以更改内容的显示方式,并且在响应数据更改时进行更新,即通过触发器。您可以在DataTemplate.Triggers
集合中使用DataTriggers来根据内容数据显示和隐藏元素。要更改整个显示,您可以例如在Grid中设置两个渲染,并使用触发器控制哪个可见。您甚至可以使您的数据模板成为ContentControl,并使用触发器更改ContentTemplate。当然,这取决于更改模板的标准是否是可绑定属性,这可能并非总是如此。
这里有一些关于选择器与触发器的简要讨论,虽然上下文略有不同。
var currentSelector = MyContentControl.ContentTemplateSelector;
MyContentControl.ContentTemplateSelector = null;
MyContentControl.ContentTemplateSelector = currentSelector;