更改datacontext属性时更改contentcontrol的数据模板
本文关键字:数据 contentcontrol datacontext 属性 更改 | 更新日期: 2023-09-27 18:28:57
我有一个绑定到对象的contentcontrol
(示例中为DataContext的data
属性)。每当data
引用的对象发生更改时,我都希望重新选择datatemplate
。我该怎么做?
<ContentControl Name="rootData" Content="{Binding data}"
ContentTemplateSelector="{StaticResource myTemplateSelector}"/>
如果您正在更改整个数据类型,那么您的视图应该如下所示,唯一的区别是删除键并使用DataType作为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");
}
}
}
如果您有相同的数据类型和不同的data值,那么您可以使用DataTemplate Selector,如下所示。否则,只需使用DataTemplate的DataType属性,您甚至不需要数据模板选择器。以下是每次更改数据时选择模板的示例代码。
主窗口.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>
下面是代码隐藏,理想情况下应该使用命令来处理按钮单击,但为了快速示例,我在代码隐藏中实现了只是为了触发数据的更改。
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";
}
}
以下是主窗口的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");
}
}
}
}
数据模板选择器
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);
}
}
}
从Rachel那里找到了一个可能的解决方案:动态更改数据模板
DataTemplateSelector不会在PropertyChange上触发,但设置触发器对我来说很有用!