我有contentcontrol
绑定到对象(示例中的DataContext的data
属性)。每当data
引用的对象发生更改时,我都想重新选择datatemplate
。我怎么能这样做?
<ContentControl Name="rootData" Content="{Binding data}"
ContentTemplateSelector="{StaticResource myTemplateSelector}"/>
答案 0 :(得分:1)
如果您有相同的数据类型和不同的Data值,那么您可以使用DataTemplate Selector,如下所示,否则只需使用DataTemplate的DataType属性,您甚至不需要datatemplate选择器。 下面是每次更改数据时选择模板的示例代码。
MainWindow.xaml
<Window x:Class="TextBindingFormatting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TextBindingFormatting"
Title="MainWindow" Height="350" Width="555">
<Window.Resources>
<local:MyTemplateSelector x:Key="MyTemplateSelector"></local:MyTemplateSelector>
<DataTemplate x:Key="Template1">
<StackPanel Orientation="Horizontal">
<Label>Label 1</Label>
<Label>Label 2</Label>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="Template2">
<StackPanel Orientation="Vertical">
<Label>Label 1</Label>
<Label>Label 2</Label>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<StackPanel>
<ContentControl Content="{Binding Data}" ContentTemplateSelector="{StaticResource MyTemplateSelector}"></ContentControl>
<Button Content="Change DataTemplate" Click="ButtonBase_OnClick"></Button>
</StackPanel>
</Grid>
下面是Code Behind,理想情况下按钮点击应该使用命令来处理,但是对于快速示例我在代码后面实现了只是为了触发数据更改。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel() {Data = "1"};
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var vm = this.DataContext as MainWindowViewModel;
vm.Data = "2";
}
}
以下是MainWindow的ViewModel
namespace TextBindingFormatting.ViewModels
{
public class MainWindowViewModel : INotifyPropertyChanged
{
private string _data;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public string Data
{
get { return _data; }
set
{
_data = value;
OnPropertyChanged("Data");
}
}
}
}
DataTemplate Selector
namespace TextBindingFormatting
{
public class MyTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var element = container as FrameworkElement;
if (element == null || item == null)
return base.SelectTemplate(item, container);
if (item.ToString() == "1")
return element.FindResource("Template1") as DataTemplate;
if (item.ToString() == "2")
return element.FindResource("Template2") as DataTemplate;
return base.SelectTemplate(item, container);
}
}
}
答案 1 :(得分:1)
如果您要更改整个数据类型,那么您的视图应如下所示,唯一的区别是删除键并使用DataType for DataTemplate,这称为隐式数据模板
<Window x:Class="TextBindingFormatting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TextBindingFormatting"
xmlns:viewModels="clr-namespace:TextBindingFormatting.ViewModels"
Title="MainWindow" Height="350" Width="555">
<Window.Resources>
<local:MyTemplateSelector x:Key="MyTemplateSelector"></local:MyTemplateSelector>
<DataTemplate DataType="{x:Type viewModels:Student}">
<StackPanel Orientation="Horizontal">
<Label>Id</Label>
<TextBlock Text="{Binding Id}"></TextBlock>
<Label>Name</Label>
<TextBlock Text="{Binding Name}"></TextBlock>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Parent}">
<StackPanel Orientation="Vertical">
<Label>Name</Label>
<TextBlock Text="{Binding Name}"></TextBlock>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<StackPanel>
<ContentControl Content="{Binding Data}" >
</ContentControl>
<Button Content="Change DataTemplate" Click="ButtonBase_OnClick"></Button>
</StackPanel>
</Grid>
背后的代码
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel() {Data = new Student{Id = 1, Name = "Student"}};
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var vm = this.DataContext as MainWindowViewModel;
vm.Data = new Parent() {Name = "This is parent"};
}
}
我有两个课程如下
public class Student : INotifyPropertyChanged
{
private string _name;
private int _id;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public string Name {
get { return _name; }
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public int Id
{
get { return _id; }
set
{
_id = value;
OnPropertyChanged("Id");
}
}
}
另一个
public class Parent : INotifyPropertyChanged
{
private string _name;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged("Name");
}
}
}
答案 2 :(得分:0)
从Rachel找到了一个可能的解决方案: Change Data template dynamically
DataTemplateSelector不会触发PropertyChange,但设置触发器可以帮我完成工作!