c# - 当 T 中的属性更改时刷新 ObservableCollection<T> - WPF MVVM

标签 c# wpf xaml mvvm

我有一个ListBox我将其绑定(bind)到 ObservableCollection<Series>在 View 模型中。每次用户单击“删除”按钮时,Delete DelegateCommand对于特定项目,在 Series 内执行类,该项目将从数据库中删除。

我正在寻找某种方法来更新 ObservableCollection<Series>当发生这种情况时,相关项目在删除后就会立即从 XAML View 中删除。

目前这种情况还没有发生,我对 WPF 还比较陌生,并且已经尝试让它工作好几天了,请指出我哪里出错了:

相关 XAML:

<ListBox ItemsSource="{Binding SeriesCollection}" Name="lbSeries" Background="#6E7587" ItemContainerStyle="{StaticResource highlightStyle}" SelectionMode="Single" AlternationCount="2" Grid.Row="2" ScrollViewer.VerticalScrollBarVisibility="Auto">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="200" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBox Margin="5,0" FontSize="14" Name="txtName" Text="{Binding Name}" Width="190" Height="30" Grid.Column="0" />
                <wpfToolkit:IntegerUpDown Value="{Binding Season}"  Name="nudSeason" FontSize="14" Height="30" Width="95" Increment="1" Maximum="100000" Minimum="0" Grid.Column="1" />
                <wpfToolkit:IntegerUpDown Value="{Binding Episode}" Name="nudEpisode" FontSize="14" Height="30" Width="95" Increment="1" Maximum="100000" Minimum="0" Grid.Column="2" />
                <Button Command="{Binding Save}" Grid.Column="3" Width="60" Height="50" Cursor="Hand" ToolTip="Save program" VerticalAlignment="Center" HorizontalAlignment="Center">
                    <Button.Template>
                        <ControlTemplate>
                            <Border HorizontalAlignment="Center" VerticalAlignment="Center" >
                                <Image Source="Resources\Save.png" Width="30" Height="40" />
                            </Border>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
                <Button Command="{Binding Delete}" Grid.Column="4" Width="60" Height="50" Cursor="Hand" CommandParameter="{Binding ElementName=lbSeries,Path=SelectedItem}" ToolTip="Remove program" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="15,0">
                    <Button.Template>
                        <ControlTemplate>
                            <Border HorizontalAlignment="Center" VerticalAlignment="Center" >
                                <Image Source="Resources\Delete.png" Width="30" Height="40" />
                            </Border>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
                <Label Content="{Binding Information}" Grid.Column="5" FontSize="14" Margin="10,0" />
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

查看模型:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using SeriesTracker.Functions;
using System.Linq;

namespace SeriesTracker.Client
{
    public class SeriesTrackerViewModel : INotifyPropertyChanged
    {
        public DelegateCommand NewSeries { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        private ObservableCollection<Series> _series = new ObservableCollection<Series>();
        public ObservableCollection<Series> SeriesCollection
        {
            get { return _series; }
            set
            {
                _series = value;
                RaisePropertyChanged("SeriesCollection");
            }
        }

        public SeriesTrackerViewModel()
        {
            NewSeries = new DelegateCommand(AddNewSeries);

            DataTable table = DataAccessLayer.GetSeries();
            if (table.Rows.Count > 0)
                LoadSeries(table);
        }

        private void LoadSeries(DataTable table)
        {
            foreach (DataRow row in table.Rows)
            {
                int id = Int32.Parse(row["Id"].ToString());
                string name = row["Name"].ToString();

                int season = 0;
                int episode = 0;

                if (Int32.TryParse(row["Season"].ToString(), out season) &&
                    Int32.TryParse(row["Episode"].ToString(), out episode))
                {
                    var series = new Series(id, name, season, episode);
                    SeriesCollection.Add(series);
                }
            }
        }

        public void AddNewSeries()
        {
            SeriesCollection.AddSeries();
        }

        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

系列类:

using System;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace SeriesTracker.Functions
{
    public class Series : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private DelegateCommand _save;
        public DelegateCommand Save 
        {
            get { return _save; }
            set
            {
                _save = value;
                RaisePropertyChanged("Save");
            }
        }

        private DelegateCommand _delete;
        public DelegateCommand Delete 
        { 
            get{return _delete;}
            set
            {
                _delete = value;
                RaisePropertyChanged("Delete");
            }
        }

        public int Id { get; set; }

        string _name;
        public String Name
        {
            get { return _name; } 
            set
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }

        int _season;
        public Int32 Season 
        {
            get { return _season; } 
            set
            {
                _season = value;
                RaisePropertyChanged("Season");
            }
        }

        int _episode;
        public Int32 Episode 
        {
            get { return _episode; }
            set
            {
                _episode = value;
                RaisePropertyChanged("Episode");
            }
        }

        string _information;
        public String Information 
        {
            get { return _information; }
            set
            {
                _information = value;
                RaisePropertyChanged("Information");
            }
        }

        public Series(int id,string name,int season, int episode)
        {
            Id = id;
            Name = name;
            Season = season;
            Episode = episode;

            Save = new DelegateCommand(SaveItem);
            Delete = new DelegateCommand(DeleteItem);
        }

        public void DeleteItem()
        {
            var selectedItem = this;
            if (selectedItem.Id != -1)
            {
                DataAccessLayer.Delete(selectedItem.Id);
            }
        }

        public void SaveItem()
        {
            var selectedItem = this;
            if (selectedItem.Id == -1)
                DataAccessLayer.AddEntry(selectedItem.Name,selectedItem.Season,selectedItem.Episode);
            else
                DataAccessLayer.Update(selectedItem.Id,
                    selectedItem.Name,selectedItem.Season,selectedItem.Episode);
        }

        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

最佳答案

您不应该将DeleteCommand保留在Series类中,它应该位于 View 模型上。

在 View 模型中,您可以轻松更新 ObservableCollection。

您需要在 ViewModel 上使用 Type Series 的通用委托(delegate)命令,并且在 XAML 上您需要在命令参数上传递 {Binding}。

查看模型 C#:-

DelegateCommand<Series> DeleteCommand { get; set; } 
DeleteCommand = new RelayCommand<Series>(OnDelete); 

// This method will gets execute on click the of Delete Button1
private void OnDelete(Series series) 
{
}

XAML:- 在“删除”按钮上更改绑定(bind)和命令参数值

CommandParameter="{Binding }"
Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"

希望这对您有帮助

关于c# - 当 T 中的属性更改时刷新 ObservableCollection<T> - WPF MVVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11928887/

相关文章:

c# - 如何从 C# 文件中加载 UWP 格式的图像

c# - 使用附加属性在 XAML 中为 WPF 元素设置动画?

c# - wpf/mvvm - 如何制作一个组合框,从 mvvm 中的选定项目中设置特定值

c# - 我可以在 Xaml 中使用 Device.OnPlatform 设置设备特定 View 吗?

c# - 未找到具有显式 ElementName 的 WPF DataBinding

c# - C# 和 java 中的 volatile 有什么区别?

C# 无法将 T 转换为 T

c# - MVVM 和 View/ViewModel 层次结构

C# - 禁用 CS0444 警告

WPF:自定义控件属性已被另一个自定义控件错误注册