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

alen0pnh  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(82)

我想不出办法来保存我的命。
我有一个简单的WPF表单,我在文本框中输入数据,用户可以单击插入并将其保存到数据库。我还有一个数据网格,它显示了所有的值。
在插入新项后,我无法让数据网格用完整的值列表“刷新”。我已经在谷歌上搜索了好几天,但我就是找不出我遗漏了哪一行来与UI进行通信以刷新网格视图。
请帮帮我,看在上帝的份上,请有人帮我摆脱这个菜鸟的噩梦
这是我的ViewModel

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 Form 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工具包中的各种属性。我读了又读又找。我就是想不通。我知道这是一些愚蠢的简单的事情,它的驾驶我疯了,因为我不能取得任何进展的实际价值,我的应用程序的原因,我旋转我的车轮上的这种废话

9wbgstp7

9wbgstp71#

首先,如果你想学习WPF,你不应该把它看作是Windows窗体。有很多很好的教程从基本概念开始。我没有找到 Categoriesproperty*,您将其作为Item Source绑定到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();
        }
    }

 private string _InputText;
 public string InputText
        {
            get { return _InputText; }
            set { _InputText= value; OnPropertyChanged(this); }

        }

    public ICommand AddCommand { get; set; }

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

     private void Add(object obj)
    {
        MessageBox.Show($"{InputText}");
    }

    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);
            }
    }

**更新:**我添加了InputText属性,你可以像这样绑定到你的textbox文本属性:

<TextBox Text="{Binding InputText}" />

相关问题