ItemsControl.ItemTemplateSelector在ItemsSource更新时不重新评估模板。 [英] ItemsControl.ItemTemplateSelector not re-evaluating template when ItemsSource is updated.
问题描述
我有一组数据,我希望能够使用两个不同的模板显示如下:
I have a collection of data which I want to be able to display using two different templates as follows:
< DataTemplate x:Key =" TemplateA">
...
< ; / DataTemplate>
< DataTemplate x:Key =" TemplateB">
...
< / DataTemplate>
< ItemsControl ItemsSource =" {Binding Items}" ; ItemTemplateSelector =" {StaticResource myTemplateSelector}" />
<DataTemplate x:Key="TemplateA">
...
</DataTemplate>
<DataTemplate x:Key="TemplateB">
...
</DataTemplate>
<ItemsControl ItemsSource="{Binding Items}" ItemTemplateSelector="{StaticResource myTemplateSelector}"
/>
推荐答案
你需要强制itemscontrol从模板中重新创建一个对象,你可以通过删除项目并将其添加到observablecollection来实现。
You need to force the itemscontrol to recreate an object from a template which you can do by removing and adding an item to an observablecollection.
这是因为模板只发生一次 - 当ui得到时提交给它的一个对象。稍后更改该对象,它不是重新模板。
This is because templating only happens the once - when the ui gets an object presented to it. Change that object later and it isn't re template.
这是一段简化的标记和代码:
Here's a piece of simplified markup and code:
<Window x:Class="wpf_Templating.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:wpf_Templating"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type local:TypeA}">
<TextBlock>AAA</TextBlock>
</DataTemplate>
<DataTemplate DataType="{x:Type local:TypeB}">
<TextBlock>B B B</TextBlock>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Content="Substitute" Command="{Binding SubstituteCommand}"/>
<ListBox ItemsSource="{Binding Objects}"
SelectedItem="{Binding SelectedRow, Mode=TwoWay}"
Grid.Row="1" />
</Grid>
</Window>
和
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using System.Collections.ObjectModel;
namespace wpf_Templating
{
public class MainWindowViewModel : ViewModelBase
{
public ObservableCollection<object> Objects { get; set; } =
new ObservableCollection<object> { new TypeA(), new TypeA(), new TypeB() };
private RelayCommand _substituteCommand;
private object _selectedRow;
public object SelectedRow
{
get { return _selectedRow; }
set { _selectedRow = value; RaisePropertyChanged(); }
}
public RelayCommand SubstituteCommand
{
get
{
return _substituteCommand
?? (_substituteCommand = new RelayCommand(
() =>
{
if(SelectedRow !=null)
{
int ix = Objects.IndexOf(SelectedRow);
Object newRow;
if(SelectedRow.GetType() == typeof(TypeA))
{
newRow = new TypeB();
}
else
{
newRow = new TypeA();
}
Objects.Remove(SelectedRow);
Objects.Insert(ix, newRow);
SelectedRow = newRow;
}
}));
}
}
}
}
因为我从有效的集合中删除了该项目。
Because I remove the item from the collection that works.
如果我注释掉行
// Objects.Remove(SelectedRow);
// Objects.Insert(ix, newRow);
然后我正在更改对象SelectRow,它将更改集合中的项目但是ui将不会重新该项目的模板。
Then I'm changing the object SelectRow which will change the item in the collection BUT the ui won't re-template that item.
这篇关于ItemsControl.ItemTemplateSelector在ItemsSource更新时不重新评估模板。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!