0

WPF、.Net 4、Prism 4.1、およびUnityを使用してPrismアプリケーションを構築しました。DirectoryModuleCatalogを使用して、実行時にモジュールを検索しています。ビューはTabControl(MainRegion)に表示されます。リージョンからビューを削除すると、ビューとビューモデルはメモリに残り、ガベージコレクションは行われません。タブアイテムは削除されます。何時間も検索した後、私は自分が間違っていることを理解できません。

これが私のブートストラッパーです:

public class Bootstrapper : UnityBootstrapper
{
    protected override void InitializeShell()
    {
        base.InitializeShell();
        App.Current.MainWindow = (Window)Shell;
        App.Current.MainWindow.Show();
    }

    protected override DependencyObject CreateShell()
    {
        var shell = new Shell();
        return shell;
    }

    protected override IModuleCatalog CreateModuleCatalog()
    {
        return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
    }
}

これが私のモジュールです:

[Module(ModuleName = "ModuleA")]
public class Module : IModule
{
    private IRegionManager _regionManager;

    public Module(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }

    public void Initialize()
    {
        var view = new UserControl1();
        //_regionManager.RegisterViewWithRegion("MainRegion", typeof(UserControl1));
        _regionManager.Regions["MainRegion"].Add(view, "ModuleA");
        _regionManager.Regions["MainRegion"].Activate(view);
    }
}

そして、リージョンに追加される私のビューのビューモデルは次のとおりです。

public class ViewModel
{
    public DelegateCommand RemoveView { get; set; }

    public ViewModel()
    {
        RemoveView = new DelegateCommand(() =>
            {
                var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
                var view = regionManager.Regions["MainRegion"].GetView("ModuleA");
                regionManager.Regions["MainRegion"].Deactivate(view);
                regionManager.Regions["MainRegion"].Remove(view);
            });
    }
}

そして、これがビューの背後にあるコードです:

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

        this.DataContext = new ViewModel();
    }
}

モジュール内のビューまたはおそらくビュー内のビューモデルをインスタンス化していることが原因である可能性があることを読みました。Red Gate Memory Profilerを使用し、DelegateCommandを使用してビューを削除すると、ビューとビューモデルの両方に、ガベージコレクションができないというフラグが立てられます。私が適切にカットしていないという参照はどこにありますか?

Antsの保持グラフは次のとおりです:https ://docs.google.com/file/d/0B4XjO9pUQxBXbGFHS1luNUtyOTg/edit?usp = Sharing

これが問題を示すテストソリューションです。

また、 CodePlexにも質問を投稿しました。

4

2 に答える 2

0

保持グラフにまだそれへのバインディング参照があるようです。

以下を読んで理解してください。

Windows Presentation Foundationでデータバインディングを使用すると、メモリリークが発生する可能性があります

それはあなたの問題かもしれないと思いますが、あなたは実際のバインディングを見せませんでした。

于 2013-02-27T06:42:38.390 に答える
0

最後に、私の問題の根本的な原因を見つけました....

Shell.xaml ではIsDefault、ボタンの 1 つを PasswordBox にバインドしていましたIsKeyboardFocused

<Button Style="{DynamicResource RedSubmitButtonStyle}" IsDefault="{Binding ElementName=passwordBox1, Path=IsKeyboardFocused}" Command="{Binding LoginCommand}" Content="Login" Height="23" HorizontalAlignment="Left" Margin="145,86,0,0" Name="button1" VerticalAlignment="Top" Width="75" />

IsKeyboardFocused、MSDNによると依存関係プロパティであるため、その目的には適しているはずです。

これは、入力したパスワードにバインドできる [パスワード] ボックスにある添付プロパティに関連していました。(WPF ツールキット拡張から) ChildWindow を非表示にした後でも、そのパスワード ボックスにフォーカスが残っていました。そのため、IsDefault を使用する代わりに、PasswordBox に keydown イベントを追加し、それが Key.Enter の場合は、フォーカスされた UI コントロールを変更して、ユーザーをプログラムにログインさせました。

Shell.xaml ファイルの全内容は次のとおりです。

<Grid x:Name="MainGrid" core:SharedResourceDictionary.MergedDictionaries="TabControlThemes;MenuThemes;ButtonThemes;DataGridThemes;TreeViewThemes;ComboBoxThemes;ListBoxThemes;GroupBoxThemes;ToggleSwitchThemes">

    <DockPanel>
        <ContentControl x:Name="menuContent" DockPanel.Dock="Top" prism:RegionManager.RegionName="MenuRegion" />
        <ContentControl DockPanel.Dock="Bottom" prism:RegionManager.RegionName="FooterRegion" />
        <ContentControl DockPanel.Dock="Top" prism:RegionManager.RegionName="MainContentRegion" />
    </DockPanel>

    <StackPanel Orientation="Horizontal" Panel.ZIndex="4" HorizontalAlignment="Right" VerticalAlignment="Top">
        <Button Visibility="{Binding IsFullScreenToggleVisible, Converter={StaticResource visConv}}" Command="{Binding ToggleFullScreen}" Height="50" Name="button4" Width="70" HorizontalAlignment="Right" Margin="0,10,10,0" VerticalAlignment="Top">
            <Button.Content>
                <TextBlock FontSize="12" FontWeight="Bold" TextWrapping="Wrap" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Text=" Toggle Full Screen" />
            </Button.Content>
        </Button>

        <Button Visibility="{Binding IsAppCloseButtonVisible, Converter={StaticResource visConv}}" Command="{Binding ShutdownApplication}" Height="50" Name="button3" Width="50" HorizontalAlignment="Right" Margin="0,10,10,0" VerticalAlignment="Top">
            <Button.Content>
                <Image Source="..\Graphics\close.png" Name="image1" />
            </Button.Content>
        </Button>
    </StackPanel>

    <xctk:ChildWindow Name="loginChildWindow" Panel.ZIndex="3" CloseButtonVisibility="Collapsed" FocusedElement="{Binding ElementName=usernameTextBox}" WindowStartupLocation="Center" WindowState="{Binding IsVisible, Mode=TwoWay, Converter={StaticResource boolConverter}}" IsModal="True" OverlayOpacity="1" Caption="Pioneer Login" Height="164" Width="261">
        <xctk:ChildWindow.OverlayBrush>
            <ImageBrush Stretch="None" Viewport="0,0,46,29" ViewportUnits="Absolute" ImageSource="../Graphics/escheresque.png" TileMode="Tile" />
        </xctk:ChildWindow.OverlayBrush>
        <xctk:BusyIndicator IsBusy="{Binding IsLoginBusy}" BusyContent="Authenticating...">
            <Grid>
                <TextBox GotFocus="usernameTextBox_GotFocus" Text="{Binding Username, UpdateSourceTrigger=PropertyChanged}" Height="23" HorizontalAlignment="Left" Margin="99,20,0,0" Name="usernameTextBox" VerticalAlignment="Top" Width="120">
                    <TextBox.InputBindings>
                        <KeyBinding Key="Enter" Command="{Binding LoginCommand}" />
                    </TextBox.InputBindings>
                </TextBox>
                <Label Content="Username" Height="28" HorizontalAlignment="Left" Margin="28,18,0,0" Name="label1" VerticalAlignment="Top" />
                <Label Content="Password" Height="28" HorizontalAlignment="Left" Margin="29,47,0,0" Name="label2" VerticalAlignment="Top" />
                <PasswordBox attach:PasswordBoxAssistant.BindPassword="True" attach:PasswordBoxAssistant.BoundPassword="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="23" HorizontalAlignment="Left" Margin="100,50,0,0" Name="passwordBox1" VerticalAlignment="Top" Width="120" />
                <Button Style="{DynamicResource RedSubmitButtonStyle}" IsDefault="{Binding ElementName=passwordBox1, Path=IsKeyboardFocused}" Command="{Binding LoginCommand}" Content="Login" Height="23" HorizontalAlignment="Left" Margin="145,86,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
                <Button Style="{DynamicResource RedSubmitButtonStyle}" Command="{Binding LazyLoginCommand}" Visibility="{Binding IsDebugMode, Converter={StaticResource visConv}}" Content="Quick Login" Height="23" HorizontalAlignment="Left" Margin="23,87,0,0" Name="button2" VerticalAlignment="Top" Width="89" />
            </Grid>
        </xctk:BusyIndicator>
    </xctk:ChildWindow>

</Grid>
于 2013-02-28T20:21:49.097 に答える