另一个用户控件中的用户控件获取WPF中收集的垃圾

时间:2018-11-07 17:15:15

标签: wpf mvvm user-controls viewmodel datacontext

我有一个带有菜单和内容控件的窗口。当我加载一个模块时,它会检查该模块是否已经打开,如果尚未创建,则将其添加到模块集合中并使其成为当前活动模块。他们是这样设置的

MainWindowViewModel.cs

private void ChangeViewModel(Object parameter)
{
    string name = (string) parameter;

    IPageViewModel page;

    if (PageViewModels.FirstOrDefault(vm => vm.Name == name) != null)
    {
        CurrentPageViewModel = PageViewModels
            .FirstOrDefault(vm => vm.Name == name);
    }
    else
    {
        if (name == "TimeSheets")
        {
            page = new TimeSheetViewModel();
        }
        else if (name == "Test")
        {
             page = new TestViewModel();
        }
        else
        {
            page = new HomeViewModel();
        }

        CurrentPageViewModel = page;
        PageViewModels.Add(page);
    }
}

MainWindow.xaml

<Window.Resources>
    <DataTemplate DataType="{x:Type local:HomeViewModel}">
        <local:Home />
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:TimeSheetViewModel}">
        <local:Timesheet />
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:TestViewModel}">
        <local:Test />
    </DataTemplate>
</Window.Resources>
<Grid x:Name="gridContent" Margin="70,42,20,20" >
    <ContentControl Content="{Binding CurrentPageViewModel}" />
</Grid>

这似乎可以在模块/页面之间进行切换,但是在一个页面上,我有一个具有自己的datacontext的用户控件,每次离开该页面时都会收集垃圾并在返回该页面时重新实例化

TimeSheet.xaml

<Grid>
    <local:EmployeeList />
</Grid>

EmployeeList.xaml

<UserControl.DataContext>
    <local:EmployeeListViewModel/>
</UserControl.DataContext>
<Grid>
    <Grid.Background>
        <SolidColorBrush Color="{StaticResource LIGHT_Main}"/>
    </Grid.Background>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="1*"/>
    </Grid.RowDefinitions>
    <Grid Grid.Row="0" Margin="5">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Label Grid.Column="0" Content="Search "/>
        <TextBox Grid.Column="1" Text="{Binding SearchParameter, UpdateSourceTrigger=PropertyChanged}" Margin="4,0,4,0"/>
        <Image Grid.Column="2" Source="pack://application:,,,/Images/Icons/SearchTiny.png" Margin="5,0,8,0"/>
    </Grid>
    <Grid Grid.Row="1" Margin="6">
        <DataGrid x:Name="gridEmployees" ItemsSource="{Binding EmployeesFiltered}" MaxHeight="500"  VerticalAlignment="Stretch" AutoGenerateColumns="False" CanUserReorderColumns="False" CanUserSortColumns="False"  HorizontalGridLinesBrush="{StaticResource GridLines}" VerticalGridLinesBrush="{StaticResource GridLines}" SelectionMode="Single" IsReadOnly="True" Width="Auto">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True" Width="200"/>
                <DataGridTextColumn Header="Badge" Binding="{Binding Badge}" IsReadOnly="True" Width="1*"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Grid>

因此,当加载完毕时,我可以搜索工作正常的员工列表,但是,一旦加载了其他模块,垃圾收集器就会删除我的搜索参数和员工列表,因此必须重新加载它们。如果我使EmployeeList.xaml的数据上下文与TimeSheet.xaml的相同,并添加必填字段,则在模块之间切换时我不会丢失搜索参数,但是EmployeeList是一个控件,我想在程序的多个位置使用它拥有自己的数据上下文会很好。

让我知道这是否没有道理,或者我的方法是错误的。

谢谢!

1 个答案:

答案 0 :(得分:0)

我不认为所有控件都必须具有自己的VM。我通常用代码编写页面具有VM,并将这些值传递给控件上的各个依赖项属性。

如果您有需要在多个控件之间共享的数据,则该数据应仅存在于一个VM上,并作为依赖属性传入。


但是...顺便说一句,我会将这些VMS作为主VM上的属性,并且每个控件datacontext都会自动继承其父级datacontext...。这时可以为每个控件获取正确的数据然后将成为绑定(路径)到原始VM上正确位置的练习。