【问题标题】:Deleting ComboBox SelectedItem from Collection从集合中删除 ComboBox SelectedItem
【发布时间】:2016-07-11 19:03:24
【问题描述】:

我基本上对所有这些都是全新的,并且正在尝试在 MVVM 的上下文中学习 C#。这将是一个简单的 CRUD 程序,现在我被困在从相应集合中删除 ComboBoxSelectedItem 上。

相关ViewModel代码:

public class AlbumViewModel
{
    private ObservableCollection<AlbumModel> albums;

    public AlbumViewModel()
    {
        this.albums = new ObservableCollection<AlbumModel>();
        LoadAlbums();
    }

    public ObservableCollection<AlbumModel> Albums
    { 
        get { return this.albums; }
    }

    public void LoadAlbums()
    {
        albums.Add(new AlbumModel("No Love/Deep Web", "Death Grips"));
        albums.Add(new AlbumModel("In Defense of the Genre", "Say Anything"));
        albums.Add(new AlbumModel("Picaresque", "The Decemberists"));
        albums.Add(new AlbumModel("In Evening Air", "Future Islands"));
        albums.Add(new AlbumModel("You're Gonna Miss It All", "Modern Baseball"));
    }

    #region RelayCommand
    private RelayCommand _deleteCommand;

    public ICommand DeleteCommand
    {
        get
        {
            if (_deleteCommand == null)
            {
                _deleteCommand = new RelayCommand(param => DeleteItem());
            }

            return _deleteCommand;
        }
    }
    #endregion

    #region DeleteItem()
    private AlbumModel SelectedItem { get; set; }

    private void DeleteItem()
    {
        if (SelectedItem != null)
        {
            this.albums.Remove(SelectedItem);
            this.SelectedItem = null;
        }
    }
    #endregion


}

相关型号代码:

public class AlbumModel : INotifyPropertyChanged
{
    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

    // AlbumModel members, properties, constructor
}

#region RelayCommand
public class RelayCommand : ICommand
{
    // fields
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    // ctors
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {

    }

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

        _execute = execute;
        _canExecute = canExecute;
    }

    // ICommand members
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

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

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

相关 XAML:

<Window x:Class="AlbumsCRUD2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:AlbumsCRUD2.ViewModels"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <local:AlbumViewModel />
</Window.DataContext>
<Window.Resources>
    <local:AlbumViewModel x:Key="albums" />
</Window.Resources>
<Grid>
<GroupBox Grid.Row="1" Grid.Column="1" HorizontalContentAlignment="Center" Header="View Existing">
        <StackPanel>
            <Label Content="Album" />

            <ComboBox Name="albumComboBox" 
                      ItemsSource="{Binding Path=Albums}" 
                      DisplayMemberPath="AlbumName" 
                      SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

            <Label Content="Artist" />
            <TextBox Text="{Binding ElementName=albumComboBox, Path=SelectedItem.ArtistName}" 
                     IsEnabled="False" />

            <Button Name="deleteBtn" Width="100" Margin="30"
                    Command="{Binding DeleteItem}"
                    Content="Delete" />
        </StackPanel>
    </GroupBox>
</Grid>
</Window>

当然还有输出中的错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'SelectedItem' property not found on 'object' ''AlbumViewModel' (HashCode=12507741)'. BindingExpression:Path=SelectedItem; DataItem='AlbumViewModel' (HashCode=12507741); target element is 'ComboBox' (Name='albumComboBox'); target property is 'SelectedItem' (type 'Object')
System.Windows.Data Error: 40 : BindingExpression path error: 'DeleteItem' property not found on 'object' ''AlbumViewModel' (HashCode=12507741)'. BindingExpression:Path=DeleteItem; DataItem='AlbumViewModel' (HashCode=12507741); target element is 'Button' (Name='deleteBtn'); target property is 'Command' (type 'ICommand')

我怀疑这是我的数据绑定错误,但我很难理解错误的含义。我将不胜感激任何关于出了什么问题的观点!

【问题讨论】:

  • 那么重复的虚拟机实例是什么,资源中的一个作为 DataContext?

标签: c# wpf xaml mvvm data-binding


【解决方案1】:
  1. SelectedItem 应该是公开的。绑定需要这个。
  2. 您尝试绑定到方法 (DeleteItem),而不是命令 (DeleteCommand)。

【讨论】:

  • 谢谢!它们看起来很简单,所以忽略它会很尴尬,但就像我说的,我对整个概念是全新的,学习它是一个过程。您能否在之前的评论中详细说明“查看优先”的含义?和重复的虚拟机?这真的很有帮助。
  • 您在Window.DataContextWindow.Resources 中都有VM 实例。 DataContext 中应该只有一个,或者你在资源中创建一个,稍后在DataContext 中引用它。视图优先意味着您在视图中创建视图模型(两次)。正如我所看到的,WPF 准备在所有情况下正确处理这是一种糟糕的方法。另一种方法是视图模型优先。搜索 google 或 stack-overflow 了解更多信息。
猜你喜欢
  • 2014-03-18
  • 2011-01-05
  • 1970-01-01
  • 2011-01-10
  • 1970-01-01
  • 1970-01-01
  • 2012-06-19
  • 2019-11-10
  • 1970-01-01
相关资源
最近更新 更多