Search code examples
c#.netwpfmvvmitemscontrol

Access my Views from bound ItemsControl


I have a typical MVVM scenario: I have an ItemsControl bound to an ObservableCollection of StepsViewModels. I define a DataTemplate so that StepViewModels are rendered as StepViews. The same happens in the StepView: I have an ItemsControl to an ObservableCollection of ParameterViewModels with a DataTemplate to render them as ParameterViews.

My problem is: I have to refresh the ItemsControl to render items added and remove items. I can refresh the ItemsControl with StepViews, because I have access to it and can call ItemsControl.Items.Refresh(). But how can I access the StepViews so I can call a Refresh method? ItemsControl Items are StepViewModels...

Here is the code:

<UserControl x:Class="mylib.EditorView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:mylib">
    <UserControl.Resources>
        <DataTemplate DataType="{x:Type my:StepViewModel}">
            <my:StepView HorizontalAlignment="Stretch"/>
        </DataTemplate>
    </UserControl.Resources>

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

        <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="1" VerticalAlignment="Top">
            <StackPanel Orientation="Vertical">
                <TextBlock Name="lblHelpRefresh" Margin="0 7 0 7" Visibility="{Binding HelpVisible}"
                       VerticalAlignment="Center" HorizontalAlignment="Center"
                       FontSize="9pt"  Foreground="#949494"
                       Text="Please click refresh to reload this list"/>
                <ItemsControl Name="stkStepContent" 
                          ItemsSource="{Binding Steps}"/>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</UserControl>

How can I access the StepView controls that render the stkStepContent Items?


Solution

  • To access your views in the codebehind you can use the DataContext of the control and cast it into the appropriate view. For example:

    ObservableCollection<StepViewModel> vmCollection = 
        stkStepContent.DataContext as ObservableCollection<StepViewModel>;
    
    foreach(StepViewModel vm in vmCollection)
    {
        vm.Refresh();
    }
    

    EDIT: Does the StepViewModel contain a second ObservableCollection with items that you are trying to refresh? If so, you might be able to wireup a PropertyChanged event so that when the internal ObservableCollection gets updated it triggers a PropertyChanged notification on the StepViewModel