wpf - 使用 TransformToAncestor 时出错 : "The specified Visual is not an ancestor of this Visual."

标签 wpf

我正在尝试获取控件相对于其窗口顶部的偏移量,但是在使用控件的 TransformToAncestor 方法时遇到了麻烦。注意:此代码在一个值转换器中,它将从控件转换为其相对于窗口的相对 Y 位置。

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    var ctrl = (Control) value;
    var win = Window.GetWindow(ctrl);
    var transform = ctrl.TransformToAncestor(win); // Exception thrown here.
    var pt = transform.Transform(new Point(0, 0));
    return pt.Y;
}

调用 Window.GetWindow工作得很好,并返回控件所在的正确窗口对象。

我是否误解了 WPF 认为的“祖先”?我认为鉴于 GetWindow 的结果,该窗口将是控件的祖先。是否存在某些嵌套模式会导致祖先线在某个点被切断?

更新:

看起来这可能是一个时间问题。当我尝试调用 TransformToAncestor事件处理程序而不是值转换器中的方法,它工作得很好。似乎值转换器必须在建立祖先关系之前实例化某些元素时运行。

不知道如何解决这个问题,因为我正在尝试使用 MVVM 模式(因此并不想使用事件处理程序,并且宁愿在我的 ViewModel 中没有 System.Windows 的东西)。

最佳答案

转换器在可视化树仍在组装时被调用,因此您的 Visual 还不是 Window 的后代。

一旦你的视觉树已经建立,你就想进行转换。这是通过使用 Dispatcher.BeginInvoke(DispatcherPriority.Render, ...) 注册 Dispatcher 回调来完成的。并在回调中做你的工作。

但是,这不能与转换器一起使用,因为转换器必须立即返回转换后的值。简单的解决方法是使用附加属性而不是转换器。就是这样:

假设您的绑定(bind)是这样的:

<SomeObject Abc="{Binding Xyz, Converter={x:Static my:Converter.Instance}}" />

创建一个包含附加属性“AbcControl”的 DependencyObject 子类“Whatever”,其 PropertyChangedCallback 进行转换并修改“Abc”属性:
public class AttachedProperties : DependencyObject
{
  public Control GetAbcControl(...
  public void SetAbcControl(...
  ... AbcControlProperty = RegisterAttached("AbcControl", typeof(Control), typeof(AttachedProperties), new PropertyMetadata
  {
    PropertyChangedCallback = (obj, e) =>
    {
      var ctrl = (Control)e.NewValue;
      Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() =>
      {
        var win = Window.GetWindow(ctrl);   
        var transform = ctrl.TransformToAncestor(win); // Exception thrown here.   
        var pt = transform.Transform(new Point(0, 0));   
        obj.SetValue(AbcProperty, pt.Y);
      });
    }
  });
}

现在你可以写:
<SomeObject AbcControl="{Binding Xyz}" />

这会将 Abc 属性设置为转换后的 Y 值。

这个一般想法有很多变化。

关于wpf - 使用 TransformToAncestor 时出错 : "The specified Visual is not an ancestor of this Visual.",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2837293/

相关文章:

c# - 自定义数据类型(结构)与数组

c# - OxyPlot 的 LinearAxis 需要 margin

c# - 如何将 BorderBrush 颜色更改为默认颜色

c# - 使用资源中的几何图形的 WPF 自定义按钮

wpf - 如何在 ItemsControl 中为 ContentControl 设置动画

c# - 用于 C# 的 Internet 连接共享 api

c# - 如何设置服务定位器来测试 MVVM 中的 View 模型

c# - 使用枚举标志位的 WPF 基于权限的授权

c# - HttpWebRequest 突然停止工作,几次请求后没有收到响应

c# - RichTextBox 的自动化支持 - 无法使用 White'sUI 获取文本