TabControl的缓存与布局的变化背后的代码

问题描述 投票:-2回答:2

与此SO问题here有关,它是更多钞票背后的代码更新等标签内容,并让缓存允许重新缓存改变UI元素?像情景我已经更新DataGrid上的一些事件上tabs滚动索引一些TabControl

dgvLogs.ScrollIntoView( log );

现在,因为标签已经缓存和上述变化不反映当用户切换到标签,其中位于dgvLogs

编辑

我在主窗口和多个选项卡保持ExTabControl其显示在它里面一些应用日志选项卡控制(datagrid)。像这样:

ExTabControl是这样的:

<controls:ExTabControl Grid.Row="1" ItemsSource="{Binding Tabs, Mode=OneWay}" >
            <controls:ExTabControl.Resources>
                <Style TargetType="{x:Type TabItem}">

                </Style>
            </controls:ExTabControl.Resources>
</controls:ExTabControl>

单有DataGrid的标签是这样的:

<DataGrid Name="dgvLogs" ItemsSource="{Binding Logs}" VerticalScrollBarVisibility="Auto" FrozenColumnCount="4">

问题:

可以说我有在ExTabControl 3选项卡,所选的选项卡是1,并从后面的代码有具有使用dgvLogs.ScrollIntoView( someInbetweenlog );为片2更新滚动索引。理想的情况是,如果我做选择选项卡,然后选择滚动索引里面dgvLogs应该在哪里someInbetweenlog所在。但不幸的是标签2滚动不动如每做后面的代码改变..

如果我使用默认选项卡控制即TabControl的insted的ExTabControl然后不出所料工作的罚款。但如果我在任何标签的移动滚动的dgvLogs则在其他选项卡反映也..

请添加评论,如果需要我会发布更多的代码。

编辑2

我已经创造了一种我所要证明的问题示例应用程序。在这个应用程序,我已经添加上下文菜单中的选项卡网格和使用Sync选项我试图滚动到视图,在闭合选择日志中找到第一个匹配的日志,在其他打开的标签。

问题:ExTabControl无法滚动到所需的日志项在不同的打开的选项卡。

https://github.com/ankushmadankar/StackOverflow54198246/

c# wpf tabcontrol
2个回答
2
投票

如果我使用默认选项卡控制即TabControl而不是ExTabControl则做工精细的预期。但是,如果我在任何标签的移动滚动的dgvLogs则在其他选项卡还反映。

TabControl的两种用途,在this post扩展:

  1. 当我们绑定ItemsSource到项目的列表,我们已经设置相同DataTemplate每个项目,TabControl将只创建一个“内容”的所有项目视图。当选择不同的选项卡项目时,View不会改变,但后盾DataContext被绑定到新选择的项目的视图模型。

是否有可能更新从后面代码的其它选项卡的内容,让缓存允许重新缓存改变UI元素?

更新将无法正常工作的原因是因为另一WPF优化,从UIElement.IsVisible

元素,其中ISVISIBLE是假的不参与输入事件(或命令),不影响任何措施或安排布局的通行证,是不可作为焦点,不是一个标签序列,并不会在命中测试报告。

您可以在缓存的元素更改属性,但有些操作需要一个UIElement是为了生效可见。

值得注意:

  • 如果你调用ScrollIntoViewDataGrid这是不可见的,它不会滚动到给定的对象。所以从你的链接项目ScrollToSelectedBehavior旨在滚动数据网格的过程中是可见的。
  • ExTabControl该方法的代码UpdateSelectedItem设置非活性contentpresenters到折叠的可见性。

鉴于您已明确要求后面的代码,

一个快速的黑客

TraceViewerView.xaml

<DataGrid IsVisibleChanged="dgvLogs_IsVisibleChanged" ... >

TraceViewerView.xaml.cs

private void dgvLogs_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
    if (sender is DataGrid dataGrid && dataGrid.IsVisible)
    {
        TraceViewerViewModel viewModel = (TraceViewerViewModel)DataContext;
        if (viewModel.Log != null)
            dataGrid.ScrollIntoView(viewModel.Log);
    }
}

一对夫妇的言论:

  • 现在,您可以作为我们直接从视图模型获取同步值删除行local:ScrollToSelectedBehavior.SelectedValue="{Binding Log}"
  • 这是一个黑客,视图是硬编码到您的视图模型,这很可能在一段时间内炸毁。

更好的办法

首先,让我们的代码松散耦合的接口。

interface ISync
{
    object SyncValue { get; }
}

TraceViewerModel.cs

public class TraceViewerViewModel : PropertyObservable, ITabItem, ISync

重命名LogSyncValue,并取代原来的代码

private TraceLog synclog;
public TraceLog Log
{
    get { return synclog; }
    private set
    {
        synclog = value;

        OnPropertyChanged();
    }
}

public object SyncValue { get; set; }

基本上,我们交易的一个接口Binding。我去在这种特定情况下使用该接口的原因是,你只需要检查标签的同步值,当你移动到它(做一个羽翼丰满Binding有点大材小用)。

接下来,让我们创建一个Behavior,你想要做什么。

相反,附加属性的,我会用交互行为,它提供了更多的封装方式来扩展功能(requires System.Windows.Interactivity)。

ScrollToSyncValueBehavior.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace WpfApp1
{
    public class ScrollToSyncValueBehavior : Behavior<DataGrid>
    {
        protected override void OnAttached()
        {
            this.AssociatedObject.IsVisibleChanged += OnVisibleChanged;
        }

        protected override void OnDetaching()
        {
            this.AssociatedObject.IsVisibleChanged -= OnVisibleChanged;
        }

        private static void OnVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is DataGrid dataGrid && dataGrid.IsVisible)
            {
                ISync viewModel = dataGrid.DataContext as ISync;
                if (viewModel?.SyncValue != null)
                    dataGrid.ScrollIntoView(viewModel.SyncValue);
            }
        }
    }
}

TraceViewerView.xaml

<UserControl x:Class="WpfApp1.TraceViewerView"

             ... 

             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:local="clr-namespace:WpfApp1"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <DataGrid CanUserAddRows="false" GridLinesVisibility="None" AutoGenerateColumns="False" 
                  ItemsSource="{Binding Logs}">
            <i:Interaction.Behaviors>
                <local:ScrollToSyncValueBehavior />
            </i:Interaction.Behaviors>

            ...

        </DataGrid>      
    </Grid>
</UserControl>

1
投票

您需要在TabControl答案描述推导this。利用该技术,为每个标签的可视化树将被保留。

请注意,如果你有很多选项卡的缓存将意味着显著的性能影响。我会建议你使用它最多的10个标签。

© www.soinside.com 2019 - 2024. All rights reserved.