简体   繁体   中英

Why doesn't my view update when adding items to the ObservableCollection

So I have this project where I have two buttons and a ListView. The ListView is separated into it's own UserControl with it's own ViewModel which contains a ObservableCollection .

I'm using a ContentPresenter to display that control because I will be using different views.

Currently, when I'm clicking the Log button, it does in fact add the string to the collection, but the view doesn't update. And it keeps adding more and more everytime I click on it. (I've put a breakpoint inside private void AddItemOne() to inspect it to prove that it adds items.)

Question Why doesn't my view update when I click the "Log" button even though it's adding items. It does add the first item if I hardcode it like this.

public LogViewModel()
{
    Logs = new ObservableCollection<string>();
    Logs.Add("Test");
}

MainWindow.xaml

<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>
<Grid>
    <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="25"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

    <Button Grid.Row="0" Grid.Column="0" Height="25" Content="Log" 
            Command="{Binding AddItemOneCommand}"/>
    <Button Grid.Row="0" Grid.Column="1" Height="25" Content="Other"
            Command="{Binding AddItemTwoCommand}"/>

    <UserControl Content="{Binding CurrentView}" Grid.Row="1" Grid.ColumnSpan="2"/>
</Grid>

MainViewModel.cs

class MainViewModel
{
    public RelayCommand AddItemOneCommand { get; set; }
    public RelayCommand AddItemTwoCommand { get; set; }


    private object _currentView;

    public object CurrentView
    {
        get { return _currentView; }
        set
        {
            _currentView = value;
        }
    }


    /* ViewModels */
    public LogViewModel LogViewModel { get; set; }

    public MainViewModel()
    {
        AddItemOneCommand = new RelayCommand(o => AddItemOne());
        AddItemTwoCommand = new RelayCommand(o => AddItemTwo());

        LogViewModel = new LogViewModel();

        _currentView = LogViewModel;


    }

    private void AddItemOne()
    {
        LogViewModel.Logs.Add("Test");
    }


    private void AddItemTwo()
    {
        LogViewModel.Logs.Add("Test");
    }
}

LogView.xaml

<UserControl.DataContext>
    <local:LogViewModel/>
</UserControl.DataContext>
<Grid>
    <ListView ItemsSource="{Binding Logs}" Background="Gray"/>
</Grid>

LogViewModel.cs

class LogViewModel
{
    public ObservableCollection<string> Logs { get; set; }

    public LogViewModel()
    {
        Logs = new ObservableCollection<string>();
    }
}

Misc

App.xaml

<Application.Resources>
    <DataTemplate DataType="{x:Type local:LogViewModel}">
        <local:LogView/>
    </DataTemplate>
</Application.Resources>

And the RelayCommand

public class RelayCommand : ICommand
{
    private Action<object> execute;
    private Func<object, bool> canExecute;

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return this.canExecute == null || this.canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        this.execute(parameter);
    }
}

Remove this from LogView.xaml:

<UserControl.DataContext>
    <local:LogViewModel/>
</UserControl.DataContext>

It creates another instance of the LogViewModel instead of using the one that you create in the MainViewModel .

You should also replace the UserControl in MainWindow.xaml with a ContentControl that binds to the CurrentView property:

<ContentControl Content="{Binding CurrentView}" Grid.Row="1" Grid.ColumnSpan="2" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM