Search code examples
c#wpfmvvmcontroltemplates

WPF - Change Controls based on listviewitem selection. Controls not updating


I'm trying to update the controls present on my Main Window based on the listviewitem selected by the user, but when the listviewitem selection is changed the controls do not update.

I used this post as reference How to dynamically change a WPF control's template using a checkbox?

EDIT: I initially used ContentTemplate but changed this to DataTemplate based on suggestions, however it still is not updating

The XMAL for my Main Window is

<Window.Resources>
    <DataTemplate x:Key="Default">
        <Grid Margin="20,280,0,0" />
    </DataTemplate>
    <DataTemplate x:Key="ERAFileSelect">
        <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="218" Margin="20,280,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
            <Grid Name="grdFileSelect">
                <Label x:Name="lblProcessContent" Content="Drag File or Manually Select File" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
                <TextBox x:Name="txtEraFileName" HorizontalAlignment="Left" Height="23" Margin="10,80,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="235"/>
                <Button x:Name="btnSelectFiles" Content="Manually Select File(s)" HorizontalAlignment="Left" Margin="10,161,0,0" VerticalAlignment="Top" Width="235" Height="45"/>
            </Grid>
        </Border>
    </DataTemplate>
    <DataTemplate x:Key="FCSFileSelect">
        <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="218" Margin="20,280,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
            <Grid Name="grdFileSelect">
                <Label x:Name="lblProcessContent" Content="Drag File or Manually Select Files" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
                <TextBox x:Name="txtFCSFileName_TQ02" HorizontalAlignment="Left" Height="23" Margin="10,40,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
                <Button x:Name="btnSelectFiles_TQ02" Content="Select" HorizontalAlignment="Left" Margin="189,37,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
                <TextBox x:Name="txtFCSFileName_TQ11" HorizontalAlignment="Left" Height="23" Margin="10,105,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
                <Button x:Name="btnSelectFiles_TQ11" Content="Selec" HorizontalAlignment="Left" Margin="189,100,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
                <TextBox x:Name="txtFCSFileName_TQ16" HorizontalAlignment="Left" Height="23" Margin="10,170,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
                <Button x:Name="btnSelectFiles_TQ16" Content="Select" HorizontalAlignment="Left" Margin="189,165,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
            </Grid>
        </Border>
    </DataTemplate>
</Window.Resources>
<Grid Margin="0,0,2,0">
    <GroupBox x:Name="gbxProgress" Header="Progress" HorizontalAlignment="Left" Margin="298,105,0,0" VerticalAlignment="Top" Height="445" Width="462" Foreground="Black">
        <ListBox x:Name="lbxProgress" HorizontalAlignment="Left" Height="408" Margin="10,10,0,0" VerticalAlignment="Top" Width="431" Foreground="Black" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Progress.Message}" />
    </GroupBox>
    <Button x:Name="btnStart" Content="Start" HorizontalAlignment="Left" Margin="20,513,0,0" VerticalAlignment="Top" Width="100" Height="37" IsEnabled="{Binding Properties.StartButtonEnabled}" Click="btnStart_Click"/>
    <Button x:Name="btnCancel" Content="Cancel" HorizontalAlignment="Left" Margin="177,513,0,0" VerticalAlignment="Top" Width="100" Height="37"/>
    <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="70" Margin="20,21,0,0" VerticalAlignment="Top" Width="740" CornerRadius="15">
        <Grid>
            <Image HorizontalAlignment ="Left" Margin="10" Height="50" Width="50" VerticalAlignment="Center" Source="/Lib/Icons/User.png" />
            <TextBlock Name="txtUser" FontSize="20" Height="30" Width="200" Foreground="Red" HorizontalAlignment="Left" Margin="78,19,0,19"/>
            <Image HorizontalAlignment ="Left" Margin="443,8,0,10" Height="50" Width="50" VerticalAlignment="Center" Source="Lib/Icons/Watch.png" />
            <TextBlock x:Name="txtRunTime" FontSize="20" Height="30" Width="200" Foreground="Red" HorizontalAlignment="Left" Margin="519,19,0,19" Text="{Binding AppRunTime.TimeElapsed}" />
        </Grid>
    </Border>
    <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="144" Margin="20,119,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
        <Grid>
            <Label x:Name="lblProcessSelection" Content="Process Selection" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
            <ListView x:Name="lvProcessSelection" HorizontalAlignment="Left" Height="93" Margin="10,30,0,0" VerticalAlignment="Top" Width="235" BorderThickness="0" SelectionChanged="lvProcessSelection_SelectionChanged">
                <ListViewItem Name="itmERA" Content="Expense Reserve Automation"/>
                <ListViewItem Name="itmFCS" Content="Financial Close Status"/>
                <ListViewItem Name="itmPEL" Content="Peel"/>
            </ListView>
        </Grid>
    </Border>
    <ContentControl DataContext="{Binding Properties}" Content="{Binding}">
    <ContentControl.Style>
            <Style TargetType="ContentControl">
                <Setter Property="ContentTemplate" Value="{StaticResource ERAFileSelect}"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding SelectedProcess}" Value="Expense Reserve Automation">
                        <Setter Property="ContentTemplate" Value="{StaticResource ERAFileSelect}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding SelectedProcess}" Value="Financial Close Status">
                        <Setter Property="ContentTemplate" Value="{StaticResource FCSFileSelect}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</Grid>

ViewModel Code is

public class MainWindowModel
{
    public ApplicationRunTime AppRunTime { get; set; }
    public LogMessage Progress { get; set; }

    public MainWindowProperties Properties { get; set; }

    public MainWindowModel()
    {
        AppRunTime = new ApplicationRunTime();
        Progress = new LogMessage();
        Properties = new MainWindowProperties();
        Properties.StartButtonEnabled = false;
    }
}

With the MainWindowProperties class

public class MainWindowProperties
{
    public bool StartButtonEnabled { get; set; }

    public string SelectedProcess { get; set; }
}

And within my MainWindow Constructor I have set the DataContext

        mainWindowModel = new MainWindowModel();
        this.DataContext = mainWindowModel;

When the selection from lvProcessSelection is changed the following code is executed

        if (lvProcessSelection.SelectedItems.Count > 0)
        {
            mainWindowModel.Properties.SelectedProcess = ((ListViewItem)lvProcessSelection.SelectedItem).Content.ToString();
        }
        else
        {
            mainWindowModel.Properties.SelectedProcess = string.Empty;
        }

This will update SelectedProcess within my ViewModel with either "Expense Reserve Automation" or "Financial Close Status"

I know the DataContext is set correctly for my ViewModel (but may not be for the ContentControl) as I am able to update lbxProgress with new messages and update txtRunTime with the application RunTime

However when I change the selection on lvProcessSelection nothing happens; the default controls of ERAFileSelect remains.

Could anybody point me in the right direction on how to solve this?


Solution

  • Could anybody point me in the right direction on how to solve this?

    Your MainWindowProperties class should implement the INotifyPropertyChanged interface and raise change notifications whenever the SelectedProcess property is set to a new value:

    public class MainWindowProperties : INotifyPropertyChanged
    {
        public bool StartButtonEnabled { get; set; }
    
        private string _selectedProcess;
    
        public string SelectedProcess
        {
            get { return _selectedProcess; }
            set { _selectedProcess = value; NotifyPropertyChanged(); }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    Please refer to MSDN for more information about this common interface: https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx

    Every view model/model that you bind to must implement this interface and raise change notifications for any target value in the view to be updated.