1

我一直在尝试使用数据绑定和文件 IO 概念进行练习,为此我编写了这个简单的应用程序,它读取 2 列 5 行 .csv 文件并将内容显示到 WPF 中的 Listview 中,具有我可以更改的功能我的 Listview 中第二列的值(如 2 路绑定)。

我无法获得任何信息以显示在我的窗口中。我只得到我在 MainWindow.xaml 中定义的列标题,但没有一个数据绑定工作。

这是我的视图模型代码和读取文件

namespace WpfPreview
{

public class LoadMovieData : BindableObject // My Data Context?
{
    public string MovieName { get; set; }
    private double year; public double Year { get { return year; } set { year = value; RaisePropertyChanged("Year"); } }
}


class ViewModel : BindableObject
{
    private List<LoadMovieData> obsMovies = new List<LoadMovieData>();
    public List<LoadMovieData> ObsMovies
    {
        get { return obsMovies; }
        set { obsMovies = value; RaisePropertyChanged("ObsMovies"); }
    }



    public void ReadFile()
    {

            string filepath = System.IO.Path.Combine("C:\\Users\\Param\\Desktop", "excel.csv"); // Get filepath

            using (var csvReader = new StreamReader(filepath)) // using this filepath
            {
                csvReader.ReadLine();       // read first line (headers)
                csvReader.ReadLine();       // read first line of row data

                while (!csvReader.EndOfStream) // while not end of file
                {
                    var words = csvReader.ReadLine().Split(',').ToList(); // read line to list of columns
                    var x = new LoadMovieData()  // new instance of data class
                    {
                        MovieName = words[0],
                        Year = Convert.ToDouble(words[1])
                    };

                    ObsMovies.Add(x); // add instance of data class to list variable

                }
            }

        }

    }
}

我不确定我的条款是否正确。我正在尝试遵循 MVVM 模式。我的窗口代码隐藏是这样的:

namespace WpfPreview
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();
    }
}
}

这是我的 XAML 部分:

<Window x:Class="WpfPreview.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:me="clr-namespace:WpfPreview"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Border Background="White">

        <ListView x:Name="MovieListView" ItemsSource="{Binding Path=ObsMovies}" VirtualizingStackPanel.IsVirtualizing="True" Background="Transparent">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Movie Name">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition />
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Text="{Binding ObsMovies.MovieName}" />
                                </Grid>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Year" Width="60">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Grid>
                                    <TextBlock Text="{Binding ObsMovies.Year}" />
                                </Grid>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </Border>
</Grid>

我对使用文件 IO 和数据绑定/数据上下文非常陌生。我确信某处有一个明显的错误,我正在尝试做的事情可以用一种更容易/不太复杂的方式来完成。请随时给我建议以重组我的代码。

4

1 回答 1

2

我通常将数据加载代码放在 ViewModel 构造函数中。此外,如果没有访问修饰符,我相信您的 ViewModel 类是私有的,因此您将无法从类外部调用任何内容。考虑制作它public

看起来您的 obsMovies 列表应该是ObservableCollection. obsMovies 的值实现了 PropertyChanged 通知,但是如果您向其添加项目,则该集合不会通知 UI 其集合已更改。

改变这个:

private List<LoadMovieData> obsMovies = new List<LoadMovieData>();
public List<LoadMovieData> ObsMovies
{
    get { return obsMovies; }
    set { obsMovies = value; RaisePropertyChanged("ObsMovies"); }
}

对此:

private ObservableCollection<LoadMovieData> obsMovies = new ObservableCollection<LoadMovieData>();
public ObservableCollection<LoadMovieData> ObsMovies
{
    get { return obsMovies; }
    set { obsMovies = value; RaisePropertyChanged("ObsMovies"); }
}

您必须导入 System.Collections.ObjectModel 才能使用它。

此外,看起来您的绑定可能不太正确。尝试使用以下内容:

 <ListView.View>
     <GridView>
        <GridViewColumn Header="Movie Name">
            <GridViewColumn.CellTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding ObsMovies.MovieName}" />
                    </Grid>
                </DataTemplate>
            </GridViewColumn.CellTemplate>
        </GridViewColumn>
        <GridViewColumn Header="Year" Width="60">
            <GridViewColumn.CellTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding ObsMovies.Year}" />
                    </Grid>
                </DataTemplate>
            </GridViewColumn.CellTemplate>
        </GridViewColumn>
    </GridView>
</ListView.View>

上述绑定省略了 TextBlock 绑定中的 ObsMovies。由于每一行 DataContext 都是集合中的一项,因此不需要在绑定中引用集合。只需让绑定路径从数据上下文级别开始(在本例中为 ObsMovies)。

最后,正如所承诺的,DataGrid 的示例实现:

<DataGrid HorizontalAlignment="Left" VerticalAlignment="Top" ItemsSource="{Binding ObsMovies}">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Year}" ClipboardContentBinding="{x:Null}" Header="Year"/>
        <DataGridTextColumn Binding="{Binding MovieName}" ClipboardContentBinding="{x:Null}" Header="Movie Name"/>
    </DataGrid.Columns>
</DataGrid>

要拥有允许编辑项目的文本框,在 listView 示例中,将 TextBlocks 替换为 TextBoxes,对于 DataGrid,指定一个 DataGridTemplateColumn 并将一个 TextBox 放入模板中:

<DataGridTemplateColumn ClipboardContentBinding="{x:Null}">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Property}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
于 2013-04-16T16:35:40.887 回答