views:

78

answers:

2

Hi! 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?

+1  A: 

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

Rachel
I'm marking this answer accepted but it was your comment that really solved my problem. I wasn't calling OnPropertyChanged when adding to the ObservableCollection. Pretty dumb mistake.
jpsstavares
Edited my answer to include the comment you're referring to. When writing this answer I was actually going to add that question but figured I'd do it as a comment instead since it was a question and not an answer :)
Rachel
+2  A: 

Hi,

if you have an ObservableCollection then the adding and removing of items should refresh automatically. But if you just updated a property in your StepsViewModel then, StepsViewModel should be the one to alert the update either by implementing the INotifyPropertyChanged interface or by inheriting from the DependencyObject and using Dependency properties instead.

Anyway, if you really want to have the ability to manually refresh your collection, use a CollectionViewSource in your ViewModel. Then call the View.Refresh() method of your CollectionViewSource.

nathan_hc