为什么选项卡控件在更改选项卡时会重用 View 实例

发布于 2024-10-17 05:45:02 字数 1991 浏览 2 评论 0原文

我有一个遵循 MVVM 模式的 WPF 项目。

我有一个包含选项卡控件的控件。选项卡控件绑定到可观察的集合。可观察集合中的每个项目都是要显示的特定选项卡页的视图模型。

实现选项卡控件的 xaml 文件使用数据模板来选择要显示的特定用户控件,具体取决于可观察集合中视图模型的具体类型。

我观察到的奇怪行为是,当我在不同类型的两个选项卡之间进行更改时,会创建用户控件的新实例。当我在同一类型的两个选项卡之间进行更改时,WPF 会重用用户控件的同一实例,它只是更改控件上的 DataContext。

这会产生一些非常不幸的后果,例如,当在同一类型但具有不同视觉状态的两个选项卡之间进行更改时,则会显示视觉状态转换动画,而它不应该显示;改变应该是即时的。在不同类型的两个选项卡之间进行更改时也会出现一些异常。

我可以更改此行为,以便选项卡控件将为每个选项卡页保留一个用户控件实例,并且在切换到不同选项卡时不会“销毁”控件。

<UserControl.Resources>
    <DataTemplate DataType="{x:Type ViewModels:ConcreteViewModel1}" d:IsDataSource="true">
        <Views:ConcreteView1 />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:ConcreteViewModel2}" d:IsDataSource="true">
        <Views:ConcreteView2/>
    </DataTemplate>
    ...
</UserControl.Resources>

<Grid x:Name="ControlTabLayoutRoot">
    <TabControl Grid.Row="0" x:Name="Main_TabControl"
        ItemsSource="{Binding MainTabControl}"
        SelectedIndex="{Binding SelectedIndex}" 
        IsSynchronizedWithCurrentItem="True"
        HorizontalContentAlignment="Stretch" 
        VerticalContentAlignment="Stretch"
        ItemContainerStyle="{DynamicResource CustomTabItemStyle}"
        Style="{DynamicResource CustomTabControl}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock>                 
                <TextBlock.Text>
                  <MultiBinding Converter="{StaticResource tabItemHeaderConverter}">
                      <MultiBinding.Bindings>
                          <Binding/>
                          <Binding Path="ProtocolName"/>
                      </MultiBinding.Bindings>
                  </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    </TabControl.ItemTemplate>
    </TabControl>
</Grid>

I have a WPF project following an MVVM pattern.

I have one control that contains a tab control. The tab control binds to an observable collection. Each item in the observable collection is a view model for a specific tab page to be shown.

The xaml file implementing the tab control uses a data template to select a specific user control to display, depending on the concrete type of the view model in the observable collection.

The strange behavior I observe is, when I change between two tabs of a different type, a new instance of the user control is created. When I change between two tabs of the same type, WPF reuses the same instance of the user control, it just changes the DataContext on the control.

This has some very unfortunate consequences, e.g. when changing between two tabs of the same type, but with different visual state, then the visual state transition animation is displayed, where it should not; the change should be instant. Also some exceptions occur when changing between two tabs of different type.

Can I change this behavior so the tab control will hold one instance of the user control for each tab page, and not "destroy" the controls, when switching to a different tab.

<UserControl.Resources>
    <DataTemplate DataType="{x:Type ViewModels:ConcreteViewModel1}" d:IsDataSource="true">
        <Views:ConcreteView1 />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:ConcreteViewModel2}" d:IsDataSource="true">
        <Views:ConcreteView2/>
    </DataTemplate>
    ...
</UserControl.Resources>

<Grid x:Name="ControlTabLayoutRoot">
    <TabControl Grid.Row="0" x:Name="Main_TabControl"
        ItemsSource="{Binding MainTabControl}"
        SelectedIndex="{Binding SelectedIndex}" 
        IsSynchronizedWithCurrentItem="True"
        HorizontalContentAlignment="Stretch" 
        VerticalContentAlignment="Stretch"
        ItemContainerStyle="{DynamicResource CustomTabItemStyle}"
        Style="{DynamicResource CustomTabControl}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock>                 
                <TextBlock.Text>
                  <MultiBinding Converter="{StaticResource tabItemHeaderConverter}">
                      <MultiBinding.Bindings>
                          <Binding/>
                          <Binding Path="ProtocolName"/>
                      </MultiBinding.Bindings>
                  </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    </TabControl.ItemTemplate>
    </TabControl>
</Grid>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

玩世 2024-10-24 05:45:02

TabControl 在内部回收虚拟化。您可以在此 StackOverflow 问题中找到两种不同的方法来防止出现这种情况:

A TabControl does recycling virtualization internally. You can find two different approaches to prevent this in this StackOverflow questions:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文