C# WPF 行为 class,由于 windows 缩放更改,卸载 UIElement 后 AssociatedObject 为空
C# WPF Behavior class, AssociatedObject is null after the UIElement was unloaded due to windows scaling change
我是 WPF 的新手,正在尝试修复可拖动的错误 window。
我正在检查我维护的应用程序中的一个错误,我们有一个行为 class,我们用它来实现拖动机制。
当我转到 windows' 显示设置并更改缩放比例 (100%/125%/150%/175%) 时,windows 似乎处理了应用程序的 window 并重新创建它。
这是行为 class 的 AssociatedObject 成员变为 null 的地方,因此当再次调用 Loaded 事件时,我没有可使用的 AssociatedObject。
如何获取新的 AssociatedObject?
自从 UI 元素被重新创建以来,这似乎是预期的行为,但行为 class 仍然是 'alive' 但不能做任何工作,因为它不熟悉新的 UI 元素(如果我理解正确,正如我提到的,我是 WPF 的新手)
谢谢!
编辑:添加示例 class
public class SetWindowSizeBehavior : Behavior<FrameworkElement>
{
protected override void OnDetaching()
{
Console.WriteLine("detaching");
base.OnDetaching();
}
protected override void OnAttached()
{
AssociatedObject.Unloaded += AssociatedObject_Unloaded;
AssociatedObject.Loaded += AssociatedObject_Loaded;
base.OnAttached();
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
Console.WriteLine("");
var a = AssociatedObject;
}
private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
{
Detach();
}
}
在 windows 显示设置菜单中更改缩放设置后,这是调用堆栈:
AssociatedObject_Unloaded
分离
AssociatedObject_Loaded <- 这是 AssociatedObject 变为空的地方
我希望问题现在更清楚了,如果没有,我很乐意得到一些关于缺失信息的评论...
你能尝试覆盖 'OnPropertyChanged' 方法吗
public class SetWindowSizeBehavior : Behavior<FrameworkElement>
{
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (AssociatedObject == null)
{
// so, let'save the value and then reuse it when OnAttached() called
_value = e.NewValue as string;
return;
}
if (e.Property == PasswordProperty)
{
if (!_skipUpdate)
{
_skipUpdate = true;
AssociatedObject.Password = e.NewValue as string;
_skipUpdate = false;
}
}
}
protected override void OnDetaching()
{
Console.WriteLine("detaching");
base.OnDetaching();
}
protected override void OnAttached()
{
AssociatedObject.Unloaded += AssociatedObject_Unloaded;
AssociatedObject.Loaded += AssociatedObject_Loaded;
base.OnAttached();
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
Console.WriteLine("");
var a = AssociatedObject;
}
private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
{
Detach();
}
}
从这里开始:
最终我使用了@DanielFr 的想法,当我检测到 associatedObject 为空时(因为基础 class 行为在调用分离方法时将其设置为空)我使用了发送者对象并且:
if (AssociatedObject == null)
{
//If we got here then we didn't go through onAttached in this iteration
Attach((FrameworkElement)sender);
}
当 FrameworkElement 是我行为中的 T 时 class
我是 WPF 的新手,正在尝试修复可拖动的错误 window。
我正在检查我维护的应用程序中的一个错误,我们有一个行为 class,我们用它来实现拖动机制。
当我转到 windows' 显示设置并更改缩放比例 (100%/125%/150%/175%) 时,windows 似乎处理了应用程序的 window 并重新创建它。
这是行为 class 的 AssociatedObject 成员变为 null 的地方,因此当再次调用 Loaded 事件时,我没有可使用的 AssociatedObject。
如何获取新的 AssociatedObject? 自从 UI 元素被重新创建以来,这似乎是预期的行为,但行为 class 仍然是 'alive' 但不能做任何工作,因为它不熟悉新的 UI 元素(如果我理解正确,正如我提到的,我是 WPF 的新手)
谢谢!
编辑:添加示例 class
public class SetWindowSizeBehavior : Behavior<FrameworkElement>
{
protected override void OnDetaching()
{
Console.WriteLine("detaching");
base.OnDetaching();
}
protected override void OnAttached()
{
AssociatedObject.Unloaded += AssociatedObject_Unloaded;
AssociatedObject.Loaded += AssociatedObject_Loaded;
base.OnAttached();
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
Console.WriteLine("");
var a = AssociatedObject;
}
private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
{
Detach();
}
}
在 windows 显示设置菜单中更改缩放设置后,这是调用堆栈:
AssociatedObject_Unloaded
分离
AssociatedObject_Loaded <- 这是 AssociatedObject 变为空的地方
我希望问题现在更清楚了,如果没有,我很乐意得到一些关于缺失信息的评论...
你能尝试覆盖 'OnPropertyChanged' 方法吗
public class SetWindowSizeBehavior : Behavior<FrameworkElement>
{
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (AssociatedObject == null)
{
// so, let'save the value and then reuse it when OnAttached() called
_value = e.NewValue as string;
return;
}
if (e.Property == PasswordProperty)
{
if (!_skipUpdate)
{
_skipUpdate = true;
AssociatedObject.Password = e.NewValue as string;
_skipUpdate = false;
}
}
}
protected override void OnDetaching()
{
Console.WriteLine("detaching");
base.OnDetaching();
}
protected override void OnAttached()
{
AssociatedObject.Unloaded += AssociatedObject_Unloaded;
AssociatedObject.Loaded += AssociatedObject_Loaded;
base.OnAttached();
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
Console.WriteLine("");
var a = AssociatedObject;
}
private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
{
Detach();
}
}
从这里开始:
最终我使用了@DanielFr 的想法,当我检测到 associatedObject 为空时(因为基础 class 行为在调用分离方法时将其设置为空)我使用了发送者对象并且:
if (AssociatedObject == null)
{
//If we got here then we didn't go through onAttached in this iteration
Attach((FrameworkElement)sender);
}
当 FrameworkElement 是我行为中的 T 时 class