问题
I set up a ContentControl.DataTemplateSelector to my desired one.
I want that according to a command or whatever, call the ContentControl to reselect the template from the selector by either xaml or code.
Thank
回答1:
I'm not aware of any (non-kludgy) way to do this: the DataTemplateSelector is called when WPF needs to select the template, and that's a one-off decision as far as WPF is concerned. (You can kludge it by making WPF think the content has changed, e.g. by setting the content to null and then back again -- I think that would work but haven't tested it -- but this is pretty ugly!) If there is a nice way to do this I too would be interested to know!
However, there is an alternative way to change how content is displayed that does update in response to data changes, and that is through triggers. You can use DataTriggers in your DataTemplate.Triggers
collection to show and hide elements depending on the content data. To change the entire display, you could e.g. set up two renderings in a Grid, and use triggers to control which one is visible. You could even make your data template a ContentControl, and use a trigger to change the ContentTemplate. Of course this depends on the criteria for changing the template being bindable properties, which may not always be the case.
Here's some brief discussion of selectors vs. triggers, albeit in a slightly different context.
回答2:
Late to the party, I know. =)
When faced with this problem, I found it easiest to explicitly set a new TemplateSelector like
MyContentControl.ContentTemplateSelector =
new MyDataTemplateSelector();
回答3:
I guess I am even later to the party, but for a different idea that may help someone...
You could also try using a ValueConverter
on the ContentControl
s ContentTemplate
property instead of a DataTemplateSelector
.
Just have a property in your DataContext
to bind, like ScreenNumber
for example. Then in the ValueConverter
return the DataTemplate
that is associated with the ScreenNumber
.
Example 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();
}
}
Example xaml resource:
<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>
回答4:
Similar to Jens answer, instead of creating a new instance , you can use the existing instance of the DataTemplateSelector
.
var currentSelector = MyContentControl.ContentTemplateSelector;
MyContentControl.ContentTemplateSelector = null;
MyContentControl.ContentTemplateSelector = currentSelector;
来源:https://stackoverflow.com/questions/2085467/explicitly-refresh-datatemplate-from-a-datatemplateselector