我有一个包含自定义UserControl的窗口.UserControl需要知道何时关闭包含它的Window,以便它可以终止一个线程.
我最好的猜测是如何实现这一点是处理UserControl的Unloaded事件.但是,Unloaded事件似乎仅在用户实际单击以关闭窗口时触发,而不是在我以编程方式调用窗口上的Close()方法时触发.
为了便于参考,以下是我的代码的一些相关部分.
MyWindow.xaml:
<Window x:Class="Namespace.MyWindow"
xmlns:controls="clr-namespace:Namespace.Controls">
<controls:MyControl/>
</Window>
Run Code Online (Sandbox Code Playgroud)
MyControl.xaml:
<UserControl x:Class="Namespace.Controls.MyControl"
Unloaded="UserControl_Unloaded"/>
<!-- Stuff -->
</UserControl>
Run Code Online (Sandbox Code Playgroud)
MyControl.xaml.cs:
void UserControl_Unloaded(object sender, RoutedEventArgs e)
{
// Stop the thread.
}
Run Code Online (Sandbox Code Playgroud)
所以回顾一下,当我关闭"手动"窗口(alt-F4,单击红色"X"等)时,上面的UserControl_Unloaded()方法被调用,但不是来自我调用的代码中的其他地方myWindow.Close().有任何想法吗?
我对WPF比较陌生,有些东西对我来说很陌生.首先,与Windows窗体不同,WPF控件层次结构不支持IDisposable.在Windows窗体中,如果用户控件使用任何托管资源,则通过覆盖每个控件实现的Dispose方法来清理资源非常容易.
在WPF中,故事并不那么简单.我搜索了几个小时,遇到了两个基本主题:
第一个主题是微软明确指出WPF没有实现IDisposable,因为WPF控件没有非托管资源.虽然这可能是真的,但他们似乎完全错过了WPF类层次结构的用户扩展可能确实使用托管资源(直接或通过模型间接)的事实.通过不实现IDisposable,Microsoft已经有效地删除了唯一保证机制,通过该机制可以清除自定义WPF控件或窗口使用的非托管资源.
其次,我发现了一些对Dispatcher.ShutdownStarted的引用.我曾尝试使用ShutdownStarted事件,但似乎没有为每个控件触发.我有一堆WPF UserControl,我已经为ShutdownStarted实现了一个处理程序,它永远不会被调用.我不确定它是否只适用于Windows,或者WPF App类.但是它没有正确触发,每次应用程序关闭时我都会泄漏打开的PerformanceCounter对象.
清理非托管资源是否有比Dispatcher.ShutdownStarted事件更好的替代方案?是否有一些技巧来实现IDisposable,以便调用Dispose?如果可能的话,我更愿意避免使用终结器.
我有一个视图模型,用作我的自定义控件的数据源.在视图模型的构造函数中,我设置了一个WMI ManagementEventWatcher并启动它.我的视图模型实现了IDisposable,所以我在Dispose方法中停止了观察者.
当我将自定义控件嵌入到窗口中,然后关闭窗口以退出应用程序时,它会抛出一个InvalidComObjectException说法"已经与其底层RCW分离的COM对象无法使用".这是因为我的观察者,如果我不创建它,就没有例外.没有关于异常的其他信息,例如堆栈跟踪等.
我的猜测是,有些东西保留了视图模型,直到观察者使用的线程终止但在观察者停止之前,我不知道如何处理这个问题.
有什么建议?谢谢康斯坦丁
public abstract class ViewModelBase : IDisposable, ...
{
...
protected virtual void OnDispose() { }
void IDisposable.Dispose()
{
this.OnDispose();
}
}
public class DirectorySelector : ViewModelBase
{
private ManagementEventWatcher watcher;
private void OnWMIEvent(object sender, EventArrivedEventArgs e)
{
...
}
protected override void OnDispose()
{
if (this.watcher != null)
{
this.watcher.Stop();
this.watcher = null;
}
base.OnDispose();
}
public DirectorySelector()
{
try
{
this.watcher = new ManagementEventWatcher(new WqlEventQuery(...));
this.watcher.EventArrived += new EventArrivedEventHandler(this.OnWMIEvent); …Run Code Online (Sandbox Code Playgroud) 我在后面的WPF代码中有一个成员是一次性的(意味着它实现了IDisposable接口)
我没有看到任何可以从WPF中的UserControl覆盖的Dispose方法,所以我可以在我的wpf usercontrol中处理该成员
在WPF用户控件中处理成员的正确方法是什么?
它是一个用户控件,它包装了一个实现IDisposable接口的私有成员.因此,我需要在某个地方处置该成员.在传统的winform中,usercontrol有一个可以覆盖的Dispose方法,以便在覆盖中我可以处理私有成员.但是在WPF用户控件中,没有这样的东西.所以我想知道在哪里可以处理wpf usercontrol中的私有成员.
我的问题不是关于处理usercontrol,而是在哪里部署一个实现IDisposable接口的私有成员
我有一个在XAML中定义的动画(作为UserControl),它实际上每秒在两个图像之间切换:
<UserControl x:Class="KaleidoscopeApplication.Controls.RemoteAnimation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="RemoteAnimation_Loaded"
Unloaded="RemoteAnimation_Unloaded">
<Grid Canvas.Left="500" Canvas.Top="84">
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard x:Name="storyboard" RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="remote2" BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0:0:1">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:2">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Image Name="remote1" Source="/Resources/Elements/Images/341.png"/>
<Image Name="remote2" Source="/Resources/Elements/Images/342.png"/>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
它可以在窗口中使用:
<!-- Remote -->
<uControl:RemoteAnimation
x:Name="remoteAnimation"
Canvas.Left="316" Canvas.Top="156" Height="246" Width="121" />
Run Code Online (Sandbox Code Playgroud)
我的问题是,当包含动画的窗口关闭时,它会继续运行并导致泄漏.我无法通过带有storyboard.Stop()的RemoteAnimation_Unloaded()来停止动画......它不会做插孔.
我已经检查了这两个帖子,但它们不适用:
我能够进入卸载方法,但调用Stop()不会停止动画.根据我的理解,对于故事板调用Begin()可能是一个问题.isControlable参数存在重载.但是,由于动画完全在XAML中,我不确定如何影响它.