WPF 中的 DataGrid 数据绑定和 MVVM

DataGrid data binding and MVVM in WPF

具有 Window 且包含 DataGrid 的 WPF 应用程序,试图实现 MVVM 架构。有一个模型 class:

public class Book
{
    public int id {get; set;}
    public string title {get; set;}
    public string isbn {get; set;}
}

这是视图模型:

class BookViewModel
{
    public ObservableCollection<Book> Books;

    public BookViewModel()
    {
        Books = new ObservableCollection<Book>();

        // TODO: execute LoadData comand
    }
}

用于视图标记的 XAML 代码的部分片段,其中包含一个 Window:

<Window.CommandBindings>
    <CommandBinding Command="self:CustomCommands.LoadData" CanExecute="LoadDataCommand_CanExecute" Executed="LoadDataCommand_Executed"/>
</Window.CommandBindings>

<DataGrid Name="BooksDataGrid>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Title" Width="200" Binding="{Binding title}"/>
        <DataGridTextColumn Header="isbn" Width="200" Binding="{Binding isbn}"/>
    </DataGrid.Columns>
</DataGrid>

上面的视图背后的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // TODO: execute LoadData command
    }

    private void LoadDataCommand_CanExecute(object sender, CanExecuteRoutedEventArgs args)
    {
        args.CanExecute = true;
    }

    private void LoadDataCommand_Executed(object sender, ExecutedRoutedEventArgs args)
    {
       // TODO: ask the model for the data
    }
}

public static class CustomCommands
{
    public static readonly RoutedUICommand LoadData = new RoutedUICommand
        (
            "LoadData",
            "LoadData",
            typeof(CustomCommands),
            new InputGestureCollection()
            {
                // allow Ctrl+L to perform this command
                new KeyGesture(Key.L, ModifierKeys.Control)
            }
        );
}

App.xaml 的代码隐藏:

public partial class App : Application
{
    [STAThread()]
    public static void Main()
    {
        App app = new App();
        app.InitializeComponent();
        app.Run();
    }

    // bind application and show main window on startup
    // data context is default source of bindings
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        View.MainWindow mainWin = new View.MainWindow();
        ViewModel.BookViewModel bookViewModel = new ViewModel.BookViewModel();
        mainWin.DataContext = bookViewModel;
        mainWin.Show();
    }
}

我正在从 WinForms 过渡到 WPF,发现 WPF 的某些方面令人困惑。力求达到的目标和面临的问题如下:

除了初始化组件和设置数据上下文之外,window 的代码隐藏中不应包含太多代码。

public MainWindow()
{
   IntializeComponent();
   DataContext = new BookViewModel();
}

并且您的 loadData 命令将在 BookViewModel 中实现

private bool _canLoadDataExecute;
private ICommand _loadDataCommand;
public Icommand LoadDataCommand => _loadDataCommand ?? _loadDataCommand = new RelayCommand((obj) => LoadDataCommand = LoadData(), canLoadDataExecute);

public void LoadData()
{
}

要使上述代码正常工作,您还需要实施 RelayCommand.cs,相关代码可在此处找到:。此外,还有许多其他有用的在线答案和资源与 RelayCommand 实施。

第一步:您创建了一个 window,它的视图模型并通过 DataContext 连接它们。已经完成

View.MainWindow mainWin = new View.MainWindow();
ViewModel.BookViewModel bookViewModel = new ViewModel.BookViewModel();
mainWin.DataContext = bookViewModel;

第二步:修复(添加)xaml 中的绑定:

<DataGrid Name="BooksDataGrid" ItemsSource="{Binding Books}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Title" Width="200" Binding="{Binding title}"/>
        <DataGridTextColumn Header="isbn" Width="200" Binding="{Binding isbn}"/>
    </DataGrid.Columns>
</DataGrid>

第三步:修复视图模型以使绑定工作 - 绑定与属性一起工作:

class BookViewModel
{
    public ObservableCollection<Book> Books { get; private set; }

    public BookViewModel()
    {
        Books = new ObservableCollection<Book>();
    }
}

第四步:在视图模型中实现加载数据方法并从命令中调用它,并在 mainWin.Show(); 加载初始数据后