wpf ContentControl.ContentTemplateSelector 动态选择模板
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20468126/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ContentControl.ContentTemplateSelector dynamically select template
提问by SubmarineX
I set a ContentControl in the right of Window, and set Content binding Items (it's type is ObservableCollection). Now I want to achieve it: if there are no item, ContentControl select first DataTemplate, and add a item into items, ContentControl will select second DataTemplate to display some info.
我在Window的右侧设置了一个ContentControl,并设置了Content binding Items(它的类型是ObservableCollection)。现在我想实现它:如果没有项目,ContentControl选择第一个DataTemplate,并在项目中添加一个项目,ContentControl将选择第二个DataTemplate显示一些信息。
Like this:
像这样:


The problem is when I add one item into items, ContentControl didnot update and change DataTemplate, I have a try to set mode, UpdateSourceTrigger, etc., but failed. In ViewModel, after delete a item, I use this statements, it will work well <1>:
问题是当我将一个项目添加到项目中时,ContentControl没有更新和更改DataTemplate,我尝试设置模式,UpdateSourceTrigger等,但失败了。在 ViewModel 中,删除项目后,我使用此语句,它会运行良好<1>:
private void ExecuteDeleteClientCommand()
{
...
if (DeleteClient(item))
{
ObservableCollection<MyViewModel> tmp = TabItems;
TabItems = null;
TabItems = tmp;
}
}
.
.
<ContentControl
ContentTemplateSelector="{StaticResource MyDataTemplateSelector}"
Content="{Binding Items}"/>
.
.
public class SingleClientDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item,
DependencyObject container)
{
ObservableCollection<MyViewModel> obj =
item as ObservableCollection<MyViewModel>;
if (null == obj || 0 == obj.Count)
{
return App.Current.FindResource("NullItemDataTemplate") as DataTemplate;
}
return App.Current.FindResource("DefaultDataTemplate") as DataTemplate;
}
}
Edited:use this way is also failed after delete one item:
编辑:删除一项后使用这种方式也失败:
RaisePropertyChanging(ItemsPropertyName);
RaisePropertyChanged(ItemsPropertyName);
but I wonder why it work well with <1>.
但我想知道为什么它与<1>一起工作得很好。
Edited2It's the delcaration:
Edited2这是声明:
public const string ItemsPropertyName = "Items";
private ObservableCollection<MyViewModel> items = new ObservableCollection<MyViewModel>();
public ObservableCollection<SingleClientDetailViewModel> TabItems
{
get { return items; }
set
{
if (items == value) { return;}
RaisePropertyChanging(ItemsPropertyName);
items = value;
RaisePropertyChanged(ItemsPropertyName);
}
}
回答by Mat J
ContentControlwill listen only for PropertyChangedevents and not for CollectionChangedevent. You'll need to use either an ItemsControlor any of its other versions like ListViewfor this behavior.
ContentControl将只监听PropertyChanged事件而不是CollectionChanged事件。对于这种行为,您需要使用 anItemsControl或其任何其他版本ListView。
As a workaround, you can create a Stylefor the ContentControland instead of TemplateSelector, define a DataTriggeron Items.Countand set the ContentTemplateaccordingly.
Something like,
作为一种解决方法,您可以Style为ContentControl和而不是TemplateSelector定义一个DataTriggeronItems.Count并相应地设置ContentTemplate。就像是,
<ContentControl Content="{Binding Items}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{StaticResource DefaultDataTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Items}" Value="{x:Null}">
<Setter Property="ContentTemplate" Value="{StaticResource NullItemDataTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Items.Count}" Value="0">
<Setter Property="ContentTemplate" Value="{StaticResource NullItemDataTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>

