2012-05-24 106 views
2

好吧我有一个容器,我已经创建了两个数据模板。基本上,一个模板将显示5个文本框和与其绑定的对象数据,另一个模板将显示一个按钮来添加该特定对象。我分类DataTemplateSelector和它的作品,但是当我浏览我的记录时,选择器再也不会被调用。用WPF动态加载内容

那么我将如何让容器重新选择它的模板。容器是一个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(); 
         } 
        } 

这两个额外的方法是检查学生的关系是否为空,他们将创建它并将其添加到数据上下文中,否则实体框架将不保存更改。上面的数据模板基本上可以帮助我解决在尝试创建新学生时没有studentId的问题。

+1

的代码。我们需要代码。 – Snowbear

+0

这是一个猜测,但也许DataTemplateSelector只会在DataContext更改时才被调用? – Steve

+0

已添加代码。此外,我试图改变datacontext并没有做任何事情。我基本上将它改为null,然后回到这个指针。 –

回答

2

我用下面的方法强制重新应用DataTemplateSelector。

派生自ObservableCollection并添加一个引发NotifyCollectionChangedEventArgs和NotifyCollectionChangedAction.Reset的方法。

public class MyThingCollection : ObservableCollection<MyThing> 
{ 
    public void RaiseResetCollection() 
    { 
     OnCollectionChanged(new 
      NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
    } 
} 

您的视图模型公开此类型的一个实例,并且您的ItemsControl绑定到该类型。

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}" 
/> 
+0

真棒非常感谢你。 –

+0

我同意。处理这个问题的好方法 – Bjoern