我有以下代码
public partial class MyControl : UserControl
{
...
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (DataContext is MyViewModel)
{
var vm = DataContext as CameraViewModel;
var p = Parent as FrameworkElement;
while (!(p is Window))
p = p.Parent as FrameworkElement;
vm.GetTransform = () => TransformToAncestor(p);
}
}
}
在我的viewmodel中,我有一个命令处理程序代码,在我点击用户控件中的按钮时执行。
public Func<GeneralTransform> GetTransform { private get; set; }
private void OnMyCommand(object parameter){
var p = GetTransform().Transform(new Point(0,0));
}
但上述代码不起作用,因为GetTransform()
调用
The specified Visual is not an ancestor of this Visual.
我认为上面的代码已经确保p
是控件的窗口祖先,但为什么我仍然会收到此错误?
答案 0 :(得分:0)
感谢@Brian Reichle的评论,我找出原因并解决了它。
事实证明,我在选项卡控件的不同选项卡中具有相同的控件。
正如您所知,只有一个标签可以始终处于活动状态。这些控件属于当前不活动的选项卡属于不具有窗口祖先的不同可视树。
在我的情况下,这就是发生的事情:我追溯逻辑树以找出Window
对象,但this
对象属于一些不可见的标签而没有{ {1}}作为其视觉祖先。
一旦意识到这一点,解决方案就是不附加Window
个事件,而是附加Loaded
个事件。
IsVisibleChanged
注意:在 private void UserControl_IsVisibleChanged(object sender,
DependencyPropertyChangedEventArgs e)
{
if (!(bool)e.NewValue)
return;
if (DataContext is CameraViewModel)
{
SaveTransform();
}
else Dispatcher.InvokeAsync(SaveTransform);
}
private void SaveTransform()
{
var vm = DataContext as CameraViewModel;
var w = VisualTreeHelper.GetParent(this) as FrameworkElement;
while (w != null && !(w is Window))
w = VisualTreeHelper.GetParent(w) as FrameworkElement;
if (w != null)
{
vm.GetTransform = () => TransformToAncestor(w);
}
}
事件的第一次触发中,可能尚未设置数据上下文。因此,上述代码必须稍后推迟IsVisibleChanged
代码。