将项目添加到 ObservableCollection 时更新 WPF Datagrid

问题描述 投票:0回答:1

我想不出这个办法来拯救我的生命。

我有一个简单的 WPF 表单,我在文本框中输入数据,用户可以单击“插入”并将其保存到数据库中。我还有一个显示所有值的数据网格。

插入新项目后,我无法使用完整的值列表来“刷新”数据网格。我已经用谷歌搜索了好几天,但我就是不知道我缺少哪一行来与 UI 通信以刷新网格视图。

请帮助我,看在上帝的份上,请有人帮助我摆脱这个新手噩梦

这是我的视图模型

    public partial class CatView : ObservableObject
    {
        private List<Category> _Cats = Category.all.Values.ToList();
        

        public List<Category> Cats 
        {
            get { return _Cats; }
            set
            { 
                _Cats = value;
                OnPropertyChanged("Cats");                
            }
        }
}

WPF 表单 XAML

`<Window x:Class="Recycle4Core.CategoryEdit"
        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:Recycle4Core.ViewModels"
        mc:Ignorable="d"
        Title="Category Editor" Height="450" Width="800">
    <Window.DataContext>
        <local:CatView />
    </Window.DataContext>
    <Grid>
        <!--<Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="2*"/>
        </Grid.RowDefinitions>-->
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <StackPanel x:Name="InputStack"
                    Orientation="Vertical"
                    Grid.IsSharedSizeScope="True">
            <Grid x:Name="GridPanelNameInput">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="FirstColumn" />
                    <ColumnDefinition SharedSizeGroup="SecondColumn" />
                </Grid.ColumnDefinitions>
                <Label Content="Category Name" 
                       Margin="0,10,0,0" />
                <TextBox x:Name="txtINPUT" 
                         Text="{Binding SelectedCategory.name}" 
                         Height="20" 
                         Width="150" 
                         Grid.Column="1" />
            </Grid>
            <Grid x:Name="ButtonGrid">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="FirstColumn" />
                    <ColumnDefinition SharedSizeGroup="SecondColumn"/>
                    <ColumnDefinition SharedSizeGroup="ThirdColumn"/>
                </Grid.ColumnDefinitions>
                <Button x:Name="btnInsert"
                    Height="20"
                    Width="100"
                    Content="Insert"
                    Margin="20 10 0 0" 
                    Grid.Column="0"
                    Click="btnInsert_Click"
                    />
                <Button x:Name="btnUpdate"
                    Height="20"
                    Width="100"
                    Content="Update"
                    Margin="20 10 0 0" 
                    Grid.Column="1"/>
                <Button x:Name="btnDelete"
                    Height="20"
                    Width="100"
                    Content="Delete"
                    Margin="20 10 0 0" 
                    Grid.Column="2"/>
            </Grid>

            <Button x:Name="btnExit"
                    Height="40"
                    Width="150"
                    Content="EXIT"
                    Margin="0 30 0 0"
                    HorizontalAlignment="Center" 
                    />

        </StackPanel>

        <!--<DataGrid x:Name="grdCategory" 
                  Grid.Column="1" 
                  AutoGenerateColumns="False"
                  SelectedItem="{Binding Selected}"
                  >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding name}" />
            </DataGrid.Columns>
        </DataGrid>-->

        <DataGrid x:Name="grdCategory" 
                  Grid.Column="1" 
                  AutoGenerateColumns="False"
                  SelectedItem="{Binding SelectedCategory}"
                  ItemsSource="{Binding Categories}"

            >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding name}" />
            </DataGrid.Columns>
        </DataGrid>

    </Grid>
</Window>`

WPF 表单代码

`        private void btnInsert_Click(object sender, RoutedEventArgs e)
`        {
            string newName = txtINPUT.Text.ToString();
            Category test = Category.get(newName);
            if (test != null)
            {
                MessageBox.Show("This Category Already Exists, Item was not Saved", "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (txtINPUT.Text.ToString() != null )
            {

                List<Category> categoryData = new List<Category>();
                Category cat = new Category(txtINPUT.Text);
                categoryData.Add(cat);
                Category.add(cat);

                Category.Raw cats = new Category.Raw(categoryData);
                CategoryDAO.categoriesInsert(cats);
                grdCategory.Items.Refresh();
                
                CategoryDAO.loadData();
            }
        }
``

我尝试使用 ObservableCollection 而不是 List<>。我尝试了 MVVM 工具包中的各种属性。我已经阅读、搜索、阅读、搜索。我就是想不通。我知道这是一些愚蠢的简单的事情,它让我发疯,因为我无法在我的应用程序的实际价值上取得任何进展,因为我在这些废话上旋转

wpf xaml data-binding datagrid observablecollection
1个回答
0
投票

首先,如果你想学习WPF,你不应该将它视为Windows窗体。有很多很好的教程都是从基本概念开始的。 我没有找到将 Categories property 绑定到 DataGrid 作为项目源。您的代码是否缺少某些内容?

但在那之前

1.you ViewModel 类(看起来是一个窗口)应该实现 INotifyPropertyChange 接口。这样它就可以与视图通信。像这样:

public partial class CatView : INotifyPropertyChanged
{
    private ObservableCollection<Category> _Cats = Category.all.Values.ToList();

    public ObservableCollection<Category> Cats
    {
        get { return _Cats; }
        set
        {
            _Cats = value;
            OnPropertyChanged();
        }
    }

    public ICommand AddCommand { get; set; }

    public CatView()
    {
         AddCommand = new RelayCommand(Add);
    }

     private void Add(object obj)
    {
        Cats?.Add(new Category());
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

如你所见

  • 我使用 ObservableCollection 而不是 List。

2.以下是RelayCommand实现示例:

public class RelayCommand : ICommand
    {
        private readonly Action<object> execute;

        private readonly Predicate<object> canExecute;

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

   public RelayCommand(Action execute, Predicate<object> canExecute = null)
        {
            if (execute == null)
            {
                throw new System.ArgumentNullException("execute");
            }

            this.execute = delegate
            {
                execute();
            };
            this.canExecute = canExecute;
        }
  public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
        {
            this.execute = execute ?? throw new System.ArgumentNullException("execute");
            this.canExecute = canExecute;
        }
  public bool CanExecute(object parameter)
        {
            if (canExecute != null)
            {
                return canExecute(parameter);
            }

            return true;
        }
public void Execute(object parameter)
        {
            execute(parameter);
        }
}
© www.soinside.com 2019 - 2024. All rights reserved.