【问题标题】:When to clean up a command-binded control?何时清理命令绑定控件?
【发布时间】:2013-01-17 15:40:32
【问题描述】:

我有一个用户控件,它有一个CheckBox、一个Button 和一个CommandBinding。如果选中CheckBox,则启用ButtonMainWindow 使用 UserControl。当主窗口中的Button被按下时,UserControl从UI中被移除,GC.Collect()被调用,但CanExecute方法仍然运行。

我发现如果我在主窗口中单击两次按钮,CanExecute 将不再运行。看来我打电话给GC.Collect()的时机不对。

我想知道什么时候调用GC清理未使用的用户控件的好时机,这样CanExecute就不会被调用了。

XAML

<UserControl x:Class="WpfApplication1.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <RoutedUICommand x:Key="okCommand" Text="OK"/>
    </UserControl.Resources>
    <UserControl.CommandBindings>
        <CommandBinding Command="{StaticResource okCommand}" CanExecute="CommandBinding_CanExecute_1"/>
    </UserControl.CommandBindings>
    <StackPanel>
        <CheckBox Name="checkBox" Content="CheckBox"/>
        <Button Command="{StaticResource okCommand}" Content="{Binding Path=Text, Source={StaticResource okCommand}}"/>
    </StackPanel>
</UserControl>

Code behind

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    private void CommandBinding_CanExecute_1(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = checkBox.IsChecked.GetValueOrDefault(false);

        System.Media.SystemSounds.Beep.Play();
    }
}

MainWindow

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Loaded="Window_Loaded_1">
    <StackPanel>
        <Border Name="container"/>

        <Button Content="Set Null" Click="Button_Click_1"/>
    </StackPanel>
</Window>

Code behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        container.Child = null;

        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

    private void Window_Loaded_1(object sender, RoutedEventArgs e)
    {
        UserControl1 uc = new UserControl1();
        container.Child = uc;
    }
}

【问题讨论】:

  • 你到底想在这里做什么?调用 GC 方法通常不是一个好主意,在极少数情况下,您比 GC 更了解“提示”他进行收集运行。即使您调用 Collect,GC 仍然可以决定不这样做。为什么要在代码中创建 UserControl?请记住,WPF 控件的创建和清理不绑定到 GC,它是 WPF 处理的一个过程,它通常需要几个“帧”。

标签: c# wpf button user-controls commandbinding


【解决方案1】:

使用网格作为容器和 Container.Clear() 方法,忘记 GC。

【讨论】:

  • 你的意思是 Grid.Children.Clear() ,因为我在 Grid 上没有找到 Clear 方法?
  • 哦,对不起,是的,我的意思是 Grid.Children.Clear()。
【解决方案2】:

我找到了另一个解决方案。也就是卸载时调用UserControl1中的CommandBindings.Clear()

我相信这是一种巧妙的方式,因为 UserControl1 的调用者不负责 UserControl1 的清理工作。

【讨论】:

  • 只是提示,如果您使用Unloaded 事件;它可能不会像您期望的那样工作。 “不能假定仅在离开页面时才发生卸载。”
  • 谢谢。但我没有使用导航,用户控件不是页面。
  • 页面并不意味着页面意义上的,我预计msdn中的单词使用不当。它关于所有控件。这意味着即使您的视图仍然可见,您也可能会直接收到一个 Unloaded 事件,然后是一个 Loaded 事件。例如,如果用户切换 Windows 主题。
  • 好的。我会注意你提到的这种情况。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-01-17
  • 2010-12-26
  • 2019-10-04
  • 2010-12-17
  • 1970-01-01
  • 2017-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多