与此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
无法滚动到所需的日志项在不同的打开的选项卡。
如果我使用默认选项卡控制即
TabControl
而不是ExTabControl
则做工精细的预期。但是,如果我在任何标签的移动滚动的dgvLogs
则在其他选项卡还反映。
有TabControl
的两种用途,在this post扩展:
ItemsSource
到项目的列表,我们已经设置相同DataTemplate
每个项目,TabControl
将只创建一个“内容”的所有项目视图。当选择不同的选项卡项目时,View
不会改变,但后盾DataContext
被绑定到新选择的项目的视图模型。是否有可能更新从后面代码的其它选项卡的内容,让缓存允许重新缓存改变UI元素?
更新将无法正常工作的原因是因为另一WPF优化,从UIElement.IsVisible:
元素,其中ISVISIBLE是假的不参与输入事件(或命令),不影响任何措施或安排布局的通行证,是不可作为焦点,不是一个标签序列,并不会在命中测试报告。
您可以在缓存的元素更改属性,但有些操作需要一个UIElement
是为了生效可见。
值得注意:
ScrollIntoView
在DataGrid
这是不可见的,它不会滚动到给定的对象。所以从你的链接项目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
重命名Log
到SyncValue
,并取代原来的代码
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>
您需要在TabControl
答案描述推导this。利用该技术,为每个标签的可视化树将被保留。
请注意,如果你有很多选项卡的缓存将意味着显著的性能影响。我会建议你使用它最多的10个标签。