好的,我有一个容器,我已为其创建了两个数据模板。基本上,一个模板将显示 5 个文本框,其中绑定(bind)了对象数据,另一个模板将显示一个按钮来添加该特定对象。我对 DataTemplateSelector 进行了子类化,它可以工作,但是当我浏览记录时,选择器永远不会再次被调用。
那么我如何让容器重新选择它的模板。容器是 StackPanel,我已经尝试过 UpdateVisuals、InvalidateVisuals、InvalidateArrange 和 ApplyTemplate。
XAML 代码
<DataTemplate x:Key="advisorTemplate">
<StackPanel Orientation="Vertical" Margin="2,2,2,2" HorizontalAlignment="Stretch" VerticalAlignment="Top">
<StackPanel Orientation="Horizontal" Margin="2,2,2,2" HorizontalAlignment="Center">
<extToolkit:WatermarkTextBox Name="txtAcadAdv" Watermark="Acad Adv" Width="125" Margin="2" Text="{Binding Path=Adv.AcadAdv}"/>
<extToolkit:WatermarkTextBox Name="txtProgAdv" Watermark="Prog Adv" Width="125" Margin="2" Text="{Binding Path=Adv.ProgAdv}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="2,2,2,2" HorizontalAlignment="Center">
<extToolkit:WatermarkTextBox Name="txtPortAdv" Watermark="Port Adv" Width="125" Margin="2" Text="{Binding Path=Adv.PortAdv}"/>
<extToolkit:WatermarkTextBox Name="txtEleTws" Watermark="Ele Tws" Width="125" Margin="2" Text="{Binding Path=Adv.EleTws}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="2,2,2,2" HorizontalAlignment="Center">
<extToolkit:WatermarkTextBox Name="txtMatTws" Watermark="Mat Tws" Width="125" Margin="2" Text="{Binding Path=Adv.MatTws}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="addAdvisor">
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Margin="2" Name="btnAddAdvisor" Click="ButtonClick" Content="Add Advisor"/>
</DataTemplate>
组框更改内容的初始化
grpAdv.ContentTemplateSelector = _advisorSelector;
最后是选择器代码
private readonly StudentWin _win;
public AdvisorDataTemplateSelector(StudentWin win)
{
_win = win;
}
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
var sp = item as StackPanel;
var adv = sp.DataContext as Advisor;
if (adv == null)
return _win.FindResource("addAdvisor") as DataTemplate;
return _win.FindResource("advisorTemplate") as DataTemplate;
}
这是我的导航代码片段
case "btnNext":
{
if(_view.CurrentPosition < _view.Count - 1)
{
CheckForUnusedReferences(_view.GetItemAt(_view.CurrentPosition) as Student);
_view.MoveCurrentToNext();
CheckForNullReferences(_view.CurrentPosition);
grpAdv.ApplyTemplate();
}
}
另外两个方法是检查学生上的关系是否为空,他们将创建它并将其添加到我的数据上下文中,否则 Entity Framework 将不会保存更改。上面的数据模板基本上可以帮助我解决当我尝试创建新学生时没有学生 ID 的问题。
最佳答案
我使用以下方法强制重新应用 DataTemplateSelector。
从 ObservableCollection 派生并添加一个通过 NotifyCollectionChangedAction.Reset 引发 NotifyCollectionChangedEventArgs 的方法。
public class MyThingCollection : ObservableCollection<MyThing>
{
public void RaiseResetCollection()
{
OnCollectionChanged(new
NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
您的 View 模型公开此类型的实例,并且您的 ItemsControl 绑定(bind)到该实例。
public class MyViewModel : ... (view model base)
{
public MyThingCollection Items{get; private set;}
}
<ItemsControl
ItemsSource="{Binding Items}"
ItemsTemplateSelector="{StaticResource MyTemplateSelector}"
...
当您需要重新应用 DataTemplateSelector 时,请在集合上调用 RaiseResetCollection。
我通常这样使用DataTemplateSelector
public class MyTemplateSelector : DataTemplateSelector
{
public DataTemplate Template1 { get; set; }
public DataTemplate Template2 { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
... return Template1 or Template2 depending on item
}
...
}
<DataTemplate x:Key="MyTemplate1" DataType="{x:Type MyType1}">
...
</DateTemplate>
<DataTemplate x:Key="MyTemplate2" DataType="{x:Type MyType2}">
...
</DateTemplate>
<local:MyTemplateSelector
x:Key="MyTemplateSelector"
Template1="{StaticResource MyTemplate1}"
Template2="{StaticResource MyTemplate2}"
/>
关于c# - 使用 WPF 动态加载内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10741547/