C# 使用WPF动态加载内容

C# 使用WPF动态加载内容,c#,wpf,datatemplateselector,C#,Wpf,Datatemplateselector,好的,我有一个容器,我为它创建了两个数据模板。基本上,一个模板将显示5个文本框,其中包含绑定到它们的对象和数据,另一个模板将显示一个按钮来添加该特定对象。我将DataTemplateSelector子类化,它可以工作,但当我在记录中导航时,该选择器再也不会被调用 那么我该如何让容器重新选择它的模板呢。容器是一个StackPanel,我已经尝试过UpdateVisuals、InvalidateVisuals、InvalidateArrange和ApplyTemplate XAML代码 <Da

好的,我有一个容器,我为它创建了两个数据模板。基本上,一个模板将显示5个文本框,其中包含绑定到它们的对象和数据,另一个模板将显示一个按钮来添加该特定对象。我将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> 
最后是选择器代码

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();
                        }
                    }
案例“btnNext”:
{
如果(_view.CurrentPosition<_view.Count-1)
{
检查未使用的引用(_view.GetItemAt(_view.CurrentPosition)作为学生);
_view.MoveCurrentToNext();
检查空引用(_view.CurrentPosition);
grpAdv.ApplyTemplate();
}
}

另外两个方法是检查学生上的关系是否为null,他们将创建该关系并将其添加到数据上下文中,否则Entity Framework不会保存更改。上面的数据模板基本上可以帮助我解决创建新学生时没有studentId的问题。

我使用了以下方法强制重新应用DataTemplateSelector

从ObservaleCollection派生并添加一个使用NotifyCollectionChangedAction.Reset引发NotifyCollectionChangedEventArgs的方法

public class MyThingCollection : ObservableCollection<MyThing>
{
    public void RaiseResetCollection()
    {
        OnCollectionChanged(new 
            NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
}
公共类MyThingCollection:ObservableCollection
{
public void RaiseResetCollection()
{
OnCollectionChanged(新的
NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
视图模型公开此类型的实例,并且ItemsControl绑定到该实例

public class MyViewModel : ... (view model base)
{
    public MyThingCollection Items{get; private set;}
}

<ItemsControl
     ItemsSource="{Binding Items}"
     ItemsTemplateSelector="{StaticResource MyTemplateSelector}"
     ...
公共类MyViewModel:。。。(视图模型库)
{
公共MyThingCollection项{get;private set;}
}

这是一个猜测,但可能DataTemplateSelector只有在DataContext更改时才会被调用?添加了代码。我还尝试更改datacontext,但它没有做任何事情。我基本上把它改为null,然后回到这个指针。我同意可能的重复。处理这个问题的好方法
public class MyViewModel : ... (view model base)
{
    public MyThingCollection Items{get; private set;}
}

<ItemsControl
     ItemsSource="{Binding Items}"
     ItemsTemplateSelector="{StaticResource MyTemplateSelector}"
     ...
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}"
/>