我的UserControl
包含TabControl
。
<UserControl x:Class="Test.MyUC"
....
xmlns:vm="clr-namespace:Test.ViewModels"
xmlns:ikriv="clr-namespace:IKriv.Windows.Controls.Behaviors"
...
<UserControl.Resources>
<vm:MyUCVM x:Key="VM" />
</UserControl.Resources>
<UserControl.DataContext>
<StaticResourceExtension ResourceKey="VM" />
</UserControl.DataContext>
<!-- Using Ivan Krivyakov's Attached Behavior -->
<TabControl ikriv:TabContent.IsCached="True"
TabStripPlacement="Top" ItemsSource="{Binding TabList}" IsSynchronizedWithCurrentItem="True">
<TabControl.Resources>
<DataTemplate DataType="{x:Type vm:MyTab1VM}">
<v:MyTab1/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:MyTab2VM}">
<v:MyTab2/>
</DataTemplate>
</TabControl.Resources>
...
当然,在MyUCVM
中,我有TabList
。现在,到目前为止,一切正常。
当TabControl
中的一个标签(例如MyTab1)需要连续并递归地从某个外部源(当然在ViewModel
中完成)读取数据时,问题就开始了,并传递了该数据到View
(通过Binding
)来显示。即使到目前为止,一切都在发挥作用。但是,我不希望在标签不可见时运行,因为没有必要这样做。
为此,MyTab1VM
需要知道关联的视图(MyTab1
)是否为选定的标签。因此,我把它连接起来了:
MyTab1:
<Style TargetType="TabItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=OneWayToSource}" />
</Style>
MyTab1VM
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.Register("IsSelected",
typeof(bool),
typeof(MyTab1VM),
new PropertyMetadata(false, new PropertyChangedCallback(IsSelectedChanged))
);
public bool IsSelected
{
get
{
return (bool) GetValue(IsSelectedProperty);
}
set
{
SetValue(IsSelectedProperty, value);
}
}
public static void IsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.Property == IsSelectedProperty)
{
MyTab1VM vm = d as MyTab1VM ;
vm.SetupToGetData();
}
}
private void SetupToGetData()
{
if (this.IsSelected)
{
System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(100);
timer.Tick += timer_Tick;
timer.Start();
}
}
private void timer_Tick(object sender, EventArgs e)
{
if (this.IsSelected)
this.MyData = ExternalSource.GetData();
else
{
(sender as System.Windows.Threading.DispatcherTimer).Stop();
}
}
不幸的是,只有在this.IsSelected = true;
的构造函数中手动设置MyTab1VM
时,此设置才有效。将其留在构造函数中,数据不会显示在视图中。
我已设置断点并确认IsSelected
的绑定正确运行。即使计时器正在运行,也会调用ExternalSource.GetData()
。但this.MyData = ExternalSource.GetData();
并未触发从ViewModel到View的更改。
最令人费解的是,如果IsSelected
从构造函数设置为true
,则会触发相同的绑定。
那里的任何人都知道这里发生了什么?