相关疑难解决方法(0)

WPF Window.Close()不会触发UserControl.Unloaded事件

我有一个包含自定义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 events user-controls

27
推荐指数
1
解决办法
4万
查看次数

正确清理WPF用户控件

我对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?如果可能的话,我更愿意避免使用终结器.

wpf user-controls dispose finalizer

21
推荐指数
3
解决办法
2万
查看次数

如何正确清理视图模型?

我有一个视图模型,用作我的自定义控件的数据源.在视图模型的构造函数中,我设置了一个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 wmi mvvm

12
推荐指数
1
解决办法
2万
查看次数

包含IDisposable成员的WPF控件

我在后面的WPF代码中有一个成员是一次性的(意味着它实现了IDisposable接口)

我没有看到任何可以从WPF中的UserControl覆盖的Dispose方法,所以我可以在我的wpf usercontrol中处理该成员

在WPF用户控件中处理成员的正确方法是什么?

它是一个用户控件,它包装了一个实现IDisposable接口的私有成员.因此,我需要在某个地方处置该成员.在传统的winform中,usercontrol有一个可以覆盖的Dispose方法,以便在覆盖中我可以处理私有成员.但是在WPF用户控件中,没有这样的东西.所以我想知道在哪里可以处理wpf usercontrol中的私有成员.

我的问题不是关于处理usercontrol,而是在哪里部署一个实现IDisposable接口的私有成员

.net c# wpf

10
推荐指数
1
解决办法
3972
查看次数

如何停止仅在XAML中组成的WPF故事板

我有一个在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()来停止动画......它不会做插孔.

我已经检查了这两个帖子,但它们不适用:

Post1 Post2

我能够进入卸载方法,但调用Stop()不会停止动画.根据我的理解,对于故事板调用Begin()可能是一个问题.isControlable参数存在重载.但是,由于动画完全在XAML中,我不确定如何影响它.

wpf animation xaml user-controls storyboard

6
推荐指数
1
解决办法
6591
查看次数

标签 统计

wpf ×5

user-controls ×3

.net ×1

animation ×1

c# ×1

dispose ×1

events ×1

finalizer ×1

mvvm ×1

storyboard ×1

wmi ×1

xaml ×1