WPF意外控制卸载

时间:2011-03-15 10:59:55

标签: wpf user-controls wpf-controls

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

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

我有一个“ThumbnailBar”,我可以在其中导航已经打开的不同详细信息实例,想象一下AccountDetail1,AccountDetail2等。

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

当我从一种类型(例如AccontDetail3)切换到另一种不同类型(UserDetail6)时出现问题。我注意到它调用了我正在离开的控件的“Unloaded”事件,我要进行的控件是Initialized,当我浏览相同类型的实例时,这两件事都没有发生

这会给我带来一些问题,例如日历里我有一个telerik RadScheduler,它不会保存我导航到的日期,并在今天的日期重新加载。

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

编辑 - 一些代码:

这是MainView.xaml,我在其中调用 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

<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的摘录

<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都会强制卸载,这是否有意义,任何解决问题的想法?

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

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

相关帖子我已经读过: 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

1 个答案:

答案 0 :(得分:1)

如果要在itemdetails中保持状态,则应将状态置于除用于显示itemdetails的UserControl之外的其他位置。

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

因此,您建议的补丁或多或少是正确的解决方案。