关于此问题here,是否可以从后面的代码中更新其他选项卡内容,并允许缓存允许重新缓存已更改的UI元素?就像在场景中,在某些事件中,DataGrid
上的tabs
的{{1}}的滚动索引已更新,
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 Name="dgvLogs" ItemsSource="{Binding Logs}" VerticalScrollBarVisibility="Auto" FrozenColumnCount="4">
中有3个标签,选择的标签是1,并且从后面的代码中使用ExTabControl
的标签2有更新的滚动索引。理想情况下,如果我确实选择选项卡2,则选择dgvLogs.ScrollIntoView( someInbetweenlog );
内的滚动索引应该位于dgvLogs
的位置。但是不幸的是,选项卡2的滚动不会根据所做的更改而移动。
如果我确实使用默认的标签控件,即someInbetweenlog
插入了TabControl
,则它可以正常工作。但是如果我将滚动移动到ExTabControl
的任何标签中,那么它也会反映在其他标签中。.
请添加注释,如有需要,我会发布更多代码。
编辑2
我创建了示例应用程序,试图在其中演示该问题。在这个应用程序中,我在选项卡中添加了用于网格的上下文菜单,并使用dgvLogs
选项试图滚动查看在其他打开的选项卡中找到的第一个与关闭的选定日志匹配的日志。
问题:Sync
无法滚动到其他打开的选项卡中的所需日志项目。
答案 0 :(得分:2)
如果我做化妆使用默认选项卡控制的,即
TabControl
如预期代替ExTabControl
,则它工作正常。但是,如果我移动滚动任何分页为dgvLogs
,然后它被反射在其他选项卡还
有两种用途TabControl
,上延伸this post:
ItemsSource
绑定到项目列表时,并且我们为每个项目设置了相同的DataTemplate
,TabControl
将为所有项目仅创建一个“内容”视图。而且,当选择其他选项卡项目时,View
不会改变,但后盾DataContext
绑定到新选择的项目的视图模型。是否有可能更新从代码后面其它选项卡内容,并让缓存允许重新缓存改变UI元素?
究其原因,更新将不会工作是因为另一个WPF优化,从UIElement.IsVisible:
IsVisible为假的元素不参与输入事件(或命令),不影响布局的度量或排列通过,不集中,不在制表符序列中,并且不会在命中测试中报告
您可以更改缓存元素的属性,但是某些操作要求可见UIElement
才能生效。
值得注意的是:
ScrollIntoView
这是不可见的,它不会滚动到给定的对象。所以DataGrid
从你的链接项目的目的是滚动数据网格的过程中是可见的。ScrollToSelectedBehavior
该方法ExTabControl
,使非活性contentpresenters到折叠的可见性。 鉴于您已经明确要求在后面提供代码,
TraceViewerView.xaml
UpdateSelectedItem
TraceViewerView.xaml.cs
<DataGrid IsVisibleChanged="dgvLogs_IsVisibleChanged" ... >
几句话:
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}"
TraceViewerModel.cs
interface ISync
{
object SyncValue { get; }
}
重命名public class TraceViewerViewModel : PropertyObservable, ITabItem, ISync
到Log
,并替换原始代码
SyncValue
使用
private TraceLog synclog;
public TraceLog Log
{
get { return synclog; }
private set
{
synclog = value;
OnPropertyChanged();
}
}
基本上,我们在public object SyncValue { get; set; }
交易来的接口。我之所以在此特定用例中使用该界面,是因为您仅需在移至该选项卡时检查该选项卡的同步值(使Binding
完全成熟就显得有些过分)。
接下来,让我们创建一个Binding
,你想要做什么。
我将使用交互行为,而不是附加属性,该行为提供了更封装的功能扩展方式(requires System.Windows.Interactivity)。
ScrollToSyncValueBehavior.cs
Behavior
TraceViewerView.xaml
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);
}
}
}
}
答案 1 :(得分:1)
您需要按照this答案中的描述导出TabControl
。使用该技术,将保留每个选项卡的可视树。
请注意,如果您有许多选项卡,则缓存将对性能产生重大影响。我建议最多将其用于10个标签。