【问题标题】:MVVM ListView with Viewmodel of type Observable Collection not updating view具有可观察集合类型的 Viewmodel 的 MVVM ListView 不更新视图
【发布时间】:2016-01-11 01:30:33
【问题描述】:

我的问题是我在 Viewmodel 中添加了 2 个类型文件对象(出于测试原因),这是一个可观察的集合,但视图不会随着应用程序的启动而更新。 这是 Mainview.cs:

public class MainView:ObservableCollection<Files>
{
    public MainView()
    {
        Files x = new Files("picture", "jpg");
        Files x1 = new Files("soundfile", "mp3");
        Add(x);
        Add(x1);
    }}

我做错了什么?以及如何避免这个错误?如果我不更改 Files 类中的属性并且只想在创建新的 File 对象时更新视图,是否真的需要 INotifyPropertyChanged?

我上了这门课:

 public class Files:INotifyPropertyChanged
{
    private String _fileName;

    public String FileName
    {
        get { return _fileName; }
        set { _fileName = value;  OnPropertyChanged("FileName");  }
    }
    private String  _dataType;

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    public String  DataType
    {
        get { return _dataType; }
        set { _dataType = value; OnPropertyChanged("DataType"); }
    }
    public Files(string filename, string dataType)
    {
        this._fileName = filename;
        this._dataType = dataType;
    }
}

还有这个 ViewModel:

  public class MainView:ObservableCollection<Files>
{
    public MainView()
    {
        Files x = new Files("picture", "jpg");
        Files x1 = new Files("soundfile", "mp3");
        Add(x);
        Add(x1);
    }
}

并在 xaml 中做到这一点:

<Window x:Class="ClientTestDesign.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:ClientTestDesign"
    xmlns:vm="clr-namespace:ClientTestDesign.ViewModel"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525"
  >
<Window.Resources>
    <vm:MainView x:Key="View"></vm:MainView>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="75"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Button Grid.Column="0" Style="{DynamicResource ForwardBackButton}" Content="Back"></Button>
    <Button Grid.Column="1" Style="{DynamicResource StopButton}" Content="Pause"></Button>
    <Button Grid.Column="2" Style="{DynamicResource ForwardBackButton}" Content="Forward"></Button>
    <ListView Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.ColumnSpan="3">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding /FileName, Source={StaticResource View}}"></TextBlock>
                    <TextBlock Text="{Binding /FileName, Source={StaticResource View}}"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

【问题讨论】:

  • 这更多的是一个理解问题。您的 Files 类应该是您的 ViewModel。 Files 应该是您的 ViewModel 中的一个属性。
  • @KosalaW 你的意思是文件应该是可观察的集合?我的 fviewmodel 应该包含文件的属性?
  • @KosalaW 这不可能是唯一的错误,不是吗?我改了没用
  • 我会尽快写一个答案。这样你就能更好地理解它。
  • @KosalaW 好的,我很期待

标签: c# xaml mvvm view observable


【解决方案1】:

像这样改变你的代码;

你的“文件”类;这里没有太大变化。但是看看我实现属性和 OnPropertyChanged 的​​方式。

using System.ComponentModel;

namespace WpfApplication1
{
 public class File:INotifyPropertyChanged
 {
    private string _fileName;
    private string _dataType;

    public string FileName
    {
        get { return _fileName; }
        set
        {
            _fileName = value; 
            OnPropertyChanged("FileName");
        }
    }

    public string DataType
    {
        get { return _dataType; }
        set
        {
            _dataType = value;
            OnPropertyChanged("DataType");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
 }
}

这是您的 ViewModel。如您所见,此视图模型与您的完全不同。这里有一些注释的属性/方法。如果您打算实现一些命令,那么该代码可能会很有用。

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;

namespace WpfApplication1
{
    public class MainWindowViewModel1:INotifyPropertyChanged
    {
        private ObservableCollection<File> _files;
        private File _selectedFile;
        //private ICommand _getFiles;

        public ObservableCollection<File> Files
        {
            get { return _files; }
            set
            {
                _files = value;
                OnPropertyChanged("Files");
            }
        }

        public File SelectedFile
        {
            get { return _selectedFile; }
            set
            {
                _selectedFile = value;
                OnPropertyChanged("SelectedFile");
            }
        }

        //public ICommand GetFiles
        //{
        //    get { return _getFiles; }
        //    set
        //    {
        //        _getFiles = value;
        //    }
        //}

        //public void ChangeFileName(object obj)
        //{
        //    Files[0].FileName = "File_" + new Random().Next().ToString(CultureInfo.InvariantCulture);
        //}

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public MainWindowViewModel1()
        {
           Files =  new ObservableCollection<File>();
           Files.Add(new File() { FileName = "picture", DataType = "jpg"});
           Files.Add(new File() { FileName = "soundfile", DataType = "mp3" });
           //GetFiles = new RelayCommand(ChangeFileName, param => true);
        }
    }
}

您的观点;看看绑定。那是你的问题之一。

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" 
    xmlns:vm="clr-namespace:WpfApplication1">
<Window.Resources>
    <vm:MainWindowViewModel1 x:Key="View"></vm:MainWindowViewModel1>
</Window.Resources>
<Grid>
    <ListView HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Source={StaticResource View}, Path=Files, Mode=TwoWay}" SelectedItem="{Binding  Source={StaticResource View}, Path= SelectedFile, Mode=TwoWay}" Margin="28,27,31,146">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Path= FileName, Mode=TwoWay}"></TextBlock>
                    <TextBlock Text="{Binding Path= DataType, Mode=TwoWay}"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <!--<Button Content="Refresh" Command="{Binding Source={StaticResource View},Path = GetFiles}" HorizontalAlignment="Left" Height="33" Margin="347,236,0,0" VerticalAlignment="Top" Width="139"/>-->
</Grid>

【讨论】:

  • 它起作用了,我使用了你的代码并删除了我所有的额外网格和列+行定义,然后它起作用了。谢谢,最好有一个可观察的集合作为列表视图中的一个对象,我很高兴它的工作:D
【解决方案2】:

你需要设置ListView的ItemsSource。在这种情况下,它与您的 DataContext 相同,因此只需执行以下操作:

<ListView ItemsSource="{Binding}" ... etc...

【讨论】:

  • 没用,如果没有明确设置,ItemsSource 不是从 DataContext 继承的
  • 不,它与 DataContext 完全分离。使用您发布的代码对我来说效果很好,所以您必须做一些您没有向我们展示的其他事情。
  • 那么您可以看到 2 个列表对象吗?我没有改变任何它不起作用的东西:(
  • 是的,列表中有两个对象。我想说您设置 DeviceContext 的方式可能有问题...我使用了 MVVM 自动设置的 ServiceLocator,并在 MainWindow 中执行了DataContext="{Binding Source={StaticResource Locator}, Path=MainView}"。你自己怎么设置的?
  • @MarkFeldman 他使用静态资源并在绑定中指定Source。没关系。但是对于更复杂的视图,我认为使用 DataContext 要好得多。
猜你喜欢
  • 2012-10-20
  • 2017-02-07
  • 2021-05-27
  • 1970-01-01
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
相关资源
最近更新 更多