WPF 意外的控件卸载 [英] WPF unexpected control unload

查看:24
本文介绍了WPF 意外的控件卸载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 MVVM 开发 WPF 应用程序.在一个窗口中,我有一个继承自 UserControl 的控件,我们称之为 DetailView.

I'm developing a WPF application using MVVM. Inside a Window, I have a control that inherits from UserControl, lets call it DetailView.

DetailView 绑定到 VM 中的一个属性(CurrentDetail),该属性可以是不同类型的 UserDetail、AccountDetail、CalendarDetail 等,都继承自同一个类

DetailView is binded to a property in the VM (CurrentDetail) that can be of different types, UserDetail, AccountDetail, CalendarDetail, etc. All inherit from the same class

我有一个ThumbnailBar",我可以在其中导航已打开的不同详细信息实例,想象 AccountDetail1、AccountDetail2 等.

I have a "ThumbnailBar" in which I can navigate between different detail instances that have been already opened, imagine AccountDetail1, AccountDetail2, etc.

此导航处理更新 VM 中的 CurrentDetail 并使用 OnPropertyChanged 事件

This navigation is handled updating CurrentDetail in the VM and with the OnPropertyChanged event

当我从一种类型(例如AccontDetail3)切换到另一种不同的类型(UserDetail6)时,问题就出现了.我注意到它调用了我要离开的控件的Unloaded"事件,我将要访问的控件已初始化,当我浏览相同类型的实例时,这两件事都不会发生

The problem comes when I switch from one type (AccontDetail3 for example) to another different type (UserDetail6). I have noticed it calls the "Unloaded" event of the control I'm leaving and the control I'm going to is Initialized, both things don't happen when I navigate through instance of the same type

这给我带来了一些问题,比如在日历中,我有一个 Telerik RadScheduler,它不会保留我导航到的日期并重新加载今天的日期.

This causes me some problems, like in calendar where I have a telerik RadScheduler that wont keep the date I had navigated to and reload with the today date.

我知道并且我已经测试过了,我可以保存变量 SelectecTimeSlot 并继续重新加载它,但这只是一个补丁

I know and I have already tested, I could save the variable SelectecTimeSlot and keep reloading it, but that would be just a patch

编辑 - 一些代码:

这是 MainView.xaml,我在其中调用 CurrentDetailsWorkSpace

Here is MainView.xaml where I call CurrentDetailsWorkSpace

<Border x:Name="BorderExteriorContent" BorderBrush="Transparent" BorderThickness="0"
        Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2">
        <ContentControl 
             x:Name="DetalleContenidoWrkSpc"
             Background="Red"
             Height="{Binding ElementName=BorderExteriorContent,Path=ActualHeight}"
             HorizontalContentAlignment="Stretch"
             VerticalContentAlignment="Stretch"
             Content="{Binding CurrentDetailsWorkSpace}"
             VerticalAlignment="Top" Panel.ZIndex="1" />
</Border>

这里是 CalendarView(卸载的视图之一)是的,我正在使用 DataTemplates

And here is CalendarView (one of the views That unloads) and yes I'm using DataTemplates

<base:BaseUCView
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:base="clr-namespace:MRWTINT.HGC.Win.Views.Base"
mc:Ignorable="d"
xmlns:calVm="clr-namespace:MRWTINT.HGC.Win.ViewModels.Calendario"
x:Class="MRWTINT.HGC.Win.Views.Calendario.CalendarioView"
xmlns:draganddrop="clr-namespace:MRWTINT.HGC.Win.ViewModels.DragDropLib"
xmlns:Calendario="clr-namespace:MRWTINT.HGC.Win.Themes.Calendario"
Margin="0"
d:DesignWidth="730" Height="Auto"
Unloaded="BaseUcViewUnloaded">

<Border x:Name="border" Margin="0,0,30,0" BorderBrush="#FF8A8A8A" BorderThickness="1" CornerRadius="3" RenderTransformOrigin="0.5,0.5">
    <Border.RenderTransform>
        <TransformGroup>
            <ScaleTransform/>
            <SkewTransform/>
            <RotateTransform/>
            <TranslateTransform/>
        </TransformGroup>
    </Border.RenderTransform>
    <Grid >
        <Grid Background="White" Grid.IsSharedSizeScope="True">
            <Grid.Resources>

                <DataTemplate x:Key="DayWeekSlotTemplate">
                    <Border Background="Black" Opacity="0.1" MinHeight="20" MinWidth="800" />
                </DataTemplate>
                <DataTemplate x:Key="AllDaySlotTemplate">
                    <Border Background="Black" Opacity="0.1" MinHeight="44" MinWidth="800" />
                </DataTemplate>
                <DataTemplate x:Key="MonthSlotTemplate">
                    <Border Background="Black" Opacity="0.1" MinHeight="120" MinWidth="120" />
                </DataTemplate>
                <DataTemplate x:Key="TimeLineSlotTemplate">
                    <Border Background="Black" Opacity="0.1" MinHeight="800" MinWidth="110"  />
                </DataTemplate>

                <Calendario:TimeSlotTemplateSelector
                    x:Key="TimeSlotTemplateSelector"
                    MonthSlotTemplate="{StaticResource MonthSlotTemplate}"
                    TimeLineSlotTemplate="{StaticResource TimeLineSlotTemplate}"
                    AllDaySlotTemplate="{StaticResource AllDaySlotTemplate}"
                    DayWeekSlotTemplate="{StaticResource DayWeekSlotTemplate}"
                />

            </Grid.Resources>

            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <telerik:RadBusyIndicator x:Name="busyIndicator" 
                Grid.Row="1" BusyContent="{DynamicResource LBL_DetalleCalendario}" 
                IsBusy="{Binding IsBusy}" Background="{x:Null}" BorderBrush="{x:Null}"
                DisplayAfter="{Binding BusyIndicatorDelayedDisplay}">

                <telerik:RadScheduler x:Name="scheduler"
                    TimeSlotTemplateSelector="{StaticResource TimeSlotTemplateSelector}"
                    draganddrop:DragDropHelper.IsDropTarget="true"
                    Margin="0"
                    Grid.Row="1"
                    FirstDayOfWeek="Monday" FontFamily="Arial" FontSize="10.667"
                    AppointmentsSource="{Binding ActividadesView}"
                    calVm:CalendarioEventBehaviours.CalendarioCreateActividadCommand="{Binding SaveCommand}"
                    calVm:CalendarioEventBehaviours.CalendarioAddActividadCommand="{Binding AddNewActividadCommand}"
                    calVm:CalendarioEventBehaviours.CalendarioDeleteActividadCommand="{Binding DeleteActividadCommand}"
                    calVm:CalendarioEventBehaviours.CalendarioEditingActividadCommand="{Binding EditingActividadCommand}"
                    calVm:CalendarioEventBehaviours.CalendarioEditedActividadCommand="{Binding EditedActividadCommand}"
                    telerik:StyleManager.Theme="{DynamicResource RadSchedulerTheme}"
                    ToolTip="{DynamicResource LBL_ToolTip_Calendario_Generico}"
                    VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"
                    ShowsConfirmationWindowOnDelete="False"
                    OpenModalDialogs="True" Height="Auto"
                    AllDayAreaHeight="0"
                    ViewMode="{Binding CalendarioViewMode, Mode=OneWayToSource}">

                    <telerik:RadScheduler.MonthViewDefinition >
                        <telerik:MonthViewDefinition />
                    </telerik:RadScheduler.MonthViewDefinition>

                    <telerik:RadScheduler.DayViewDefinition >
                        <telerik:DayViewDefinition DayStartTime="07:00:00" />
                    </telerik:RadScheduler.DayViewDefinition >

                    <telerik:RadScheduler.TimelineViewDefinition >
                        <telerik:TimelineViewDefinition DayStartTime="07:00:00" />
                    </telerik:RadScheduler.TimelineViewDefinition>

                    <telerik:RadScheduler.RenderTransform >
                        <TransformGroup >
                            <ScaleTransform/>
                            <SkewTransform/>
                            <RotateTransform/>
                            <TranslateTransform/>
                        </TransformGroup>
                    </telerik:RadScheduler.RenderTransform>

                    <telerik:RadScheduler.WeekViewDefinition >
                        <telerik:WeekViewDefinition DayStartTime="07:00:00" />
                    </telerik:RadScheduler.WeekViewDefinition>

                    <VisualStateManager.CustomVisualStateManager>
                        <VisualStateManager />
                    </VisualStateManager.CustomVisualStateManager>

                </telerik:RadScheduler>

            </telerik:RadBusyIndicator>

            <!-- BOTONES PARTE SUPERIOR CALENDARIO -->
            <Grid x:Name="Botonera" Margin="10,4,0,0" RenderTransformOrigin="0.5,0.5" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                </Grid.RowDefinitions>

                <!-- REFRESCAR CALENDARIO -->
                <StackPanel Grid.Column="0" x:Name="PanelRefresh" Orientation="Horizontal" Cursor="Hand">
                    <Image x:Name="imgResfresh"
                        Width="16" Height="16" Source="..\..\Resources\Calendario\table_refresh.png" />
                    <Button x:Name="btnRefresh"
                        Content="{DynamicResource BTN_Refrescar}"
                        Style="{StaticResource ButtonStyle}"
                        Background="{x:Null}" FontFamily="Arial"
                        FontSize="10.667" Margin="0,0,5,0"
                        Command="{Binding RefreshCommand}" />

                    <Image x:Name="imgWeekends" Margin="10,0,0,0"
                        Width="16" Height="16" Source="..\..\Resources\Calendario\table_row_delete.png" />
                    <Button x:Name="btnWeekends"
                        Style="{StaticResource ButtonStyle}"
                        Background="{x:Null}" FontFamily="Arial"
                        FontSize="10.667" Margin="0,0,5,0"
                        Command="{Binding RefreshCommand}" />

                </StackPanel>
                <!-- /REFRESCAR CALENDARIO -->
            </Grid>
            <!-- /BOTONES PARTE SUPERIOR CALENDARIO -->

        </Grid>
    </Grid>
</Border>

这里是我也在使用 DataTemplates 的 AccountView 的摘录

Here the extract of AccountView where I'm using DataTemplates too

<DataTemplate x:Key="ImgContactoTemplate">
        <Image RenderOptions.BitmapScalingMode="NearestNeighbor"
                     Width="16" Height="16" Margin="0,1,0,0" Source="pack://application:,,,/Resources/Cuentas/user.png" />
    </DataTemplate>

    <DataTemplate x:Key="ImgOportunidadTemplate">
        <Image x:Name="imgTipoOportunidadEtapa"
                     Width="16" Height="16"
                     RenderOptions.BitmapScalingMode="NearestNeighbor"
                     Source="{Binding IDTipoEtapa, Converter={StaticResource valueToImageConverter}, ConverterParameter=EtapaOportunidadMini}"
                     VerticalAlignment="Center" HorizontalAlignment="Center" />
    </DataTemplate>

    <DataTemplate x:Key="BtCellDataTemplate">
        <Button x:Name="btnNewActivityFromOportunidad" Margin="0" Width="20" Height="20" Background="Transparent" Cursor="Hand"
                      Command="Cuentas:CuentaViewModel.NewActivityFromOportunidadCommand"
                      CommandParameter="{Binding IDOportunidad}" Padding="0"
                      VerticalAlignment="Center" HorizontalAlignment="Center"
                      Visibility="{Binding CanUserCreateNew}"
                      Style="{DynamicResource ButtonStyle}">
            <Image RenderOptions.BitmapScalingMode="NearestNeighbor" Width="16" Height="16"
                           Margin="0" Source="pack://application:,,,/Resources/Calendario/calendar_add.png" />
        </Button>
    </DataTemplate>

所以对每种类型使用不同的 DataTemplates 会强制卸载,这是有道理的,有什么解决办法吗?

So using different DataTemplates for every type forces the unloading, that makes sense, any idea to solve that?

编辑 - 对于 ResourceDictionary 中的每种类型,我都有带有 DataTemplate 的 DataTemplates.xaml,例如:

EDIT - I have DataTemplates.xaml with DataTemplate for each type in a ResourceDictionary, example:

    <DataTemplate DataType="{x:Type vmCal:CalendarioBusquedaViewModel}">
    <viewsCalendario:CalendarioBusquedaView Width="Auto" MaxWidth="Infinity"/>
</DataTemplate>

我已经读过的相关帖子:在wpf中,有没有办法在卸载控件之前执行代码......?比如卸载活动?如何在选项卡项中保留控件状态在 TabControl 中

Related posts I've already read: In wpf, is there a way to execute code before the control is unloaded...? like maybe an unloading event? How to preserve control state within tab items in a TabControl

推荐答案

如果你想在 itemdetails 中保持状态,你应该把状态放在除了用于显示 itemdetails 的 UserControls 之外的地方.

If you want to keep state across itemdetails you should put the state in something else than the UserControls that are used to display itemdetails.

当加载不同类型和相应的用户控件时,卸载用户控件(及其状态)是很正常的.

It is quite normal that the usercontrol (and thus its state) is unloaded when a different type and corresponding usercontrol is loaded.

所以您建议的补丁或多或少是正确的解决方案.

So the patch you are suggesting is more or less a correct solution.

这篇关于WPF 意外的控件卸载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆